From 46465a287bc7e5687003c88083e7b2212f599a1c Mon Sep 17 00:00:00 2001 From: Matthieu Huguet Date: Thu, 23 Jan 2020 16:30:09 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(apps)=20add=20elasticsearch=20applica?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an independant elasticsearch app with a configurable high availability cluster. It is designed to run without persistent volume and it supports rolling updates without any data loss. On the other hand, a full restart of the ES cluster (without rolling update) results in data loss and requires to recreate indexes. --- .circleci/config.yml | 87 +++++++++++++------ CHANGELOG.md | 1 + .../services/app/configs/elasticsearch.yml.j2 | 23 +++++ .../app/configs/index-template.json.j2 | 13 +++ .../app/configs/readiness-probe.sh.j2 | 57 ++++++++++++ .../app/configs/set-index-template.sh.j2 | 20 +++++ .../templates/services/app/dc.yml.j2 | 84 ++++++++++++++++++ .../app/job_set_index_template.yml.j2 | 49 +++++++++++ .../services/app/svc-discovery.yml.j2 | 25 ++++++ .../templates/services/app/svc.yml.j2 | 18 ++++ apps/elasticsearch/tray.yml | 3 + apps/elasticsearch/vars/all/main.yml | 52 +++++++++++ apps/elasticsearch/vars/settings.yml | 1 + bin/ci-test-route | 39 +++++++++ bin/ci-test-service | 36 +++++--- .../customer/eugene/development/main.yml | 1 + group_vars/customer/eugene/main.yml | 7 ++ group_vars/env_type/ci.yml | 1 + group_vars/env_type/development.yml | 1 + 19 files changed, 479 insertions(+), 39 deletions(-) create mode 100644 apps/elasticsearch/templates/services/app/configs/elasticsearch.yml.j2 create mode 100644 apps/elasticsearch/templates/services/app/configs/index-template.json.j2 create mode 100644 apps/elasticsearch/templates/services/app/configs/readiness-probe.sh.j2 create mode 100644 apps/elasticsearch/templates/services/app/configs/set-index-template.sh.j2 create mode 100644 apps/elasticsearch/templates/services/app/dc.yml.j2 create mode 100644 apps/elasticsearch/templates/services/app/job_set_index_template.yml.j2 create mode 100644 apps/elasticsearch/templates/services/app/svc-discovery.yml.j2 create mode 100644 apps/elasticsearch/templates/services/app/svc.yml.j2 create mode 100644 apps/elasticsearch/tray.yml create mode 100644 apps/elasticsearch/vars/all/main.yml create mode 100644 apps/elasticsearch/vars/settings.yml create mode 100755 bin/ci-test-route diff --git a/.circleci/config.yml b/.circleci/config.yml index 3531615ce..c6ca67a4a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -201,7 +201,7 @@ jobs: # Bootstrap app bin/ci-ansible-playbook bootstrap.yml "hello" # Test service deployed with the next route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" "/" "next" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" "/" "next" - run: name: Test the "hello" application switch @@ -209,7 +209,7 @@ jobs: # Switch next route to current bin/ci-ansible-playbook switch.yml "hello" # Test service switched to the current route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" - run: name: Test the "hello" application rollback @@ -219,13 +219,13 @@ jobs: # Switch next route to current and current to previous bin/ci-ansible-playbook switch.yml "hello" # Test service switched to the current/previous route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" "/" "previous" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" "/" "previous" # Rollback previous to current and current to next bin/ci-ansible-playbook rollback.yml "hello" # Test service switched to the current/next route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" "/" "next" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" "/" "next" # Test the redirect application test-redirect: @@ -255,7 +255,7 @@ jobs: name: Test the "www" to root domain redirection command: | # Test service switched to the current route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" "/" "www" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" "/" "www" # Test the bootstrap playbook on the "mailcatcher" application # nota bene: we use a real OpenShift cluster installed in CircleCI's VM. @@ -278,7 +278,7 @@ jobs: name: Test the "mailcatcher" application bootstrapping command: | bin/ci-ansible-playbook bootstrap.yml "mailcatcher" - bin/ci-test-service "mailcatcher" "MailCatcher" + bin/ci-test-route "mailcatcher" "MailCatcher" # Test the bootstrap playbook on the "richie" application # nota bene: we use a real OpenShift cluster installed in CircleCI's VM. @@ -303,7 +303,7 @@ jobs: # Bootstrap app bin/ci-ansible-playbook bootstrap.yml "richie" # Test service deployed with the next route - bin/ci-test-service "richie" "Django administration" "/en/admin" "next" + bin/ci-test-route "richie" "Django administration" "/en/admin" "next" - run: name: Test the "richie" application switch @@ -311,7 +311,7 @@ jobs: # Switch next route to current bin/ci-ansible-playbook switch.yml "richie" # Test service switched to the current route - bin/ci-test-service "richie" "Django administration" "/en/admin" + bin/ci-test-route "richie" "Django administration" "/en/admin" # Test the bootstrap playbook on the "forum" application # nota bene: we use a real OpenShift cluster installed in CircleCI's VM. @@ -336,7 +336,7 @@ jobs: # Bootstrap app bin/ci-ansible-playbook bootstrap.yml "forum" # Test service deployed with the next route - bin/ci-test-service "forum" "collection" "/api/v1/threads?api_key=thisisafakeapikey" "next" + bin/ci-test-route "forum" "collection" "/api/v1/threads?api_key=thisisafakeapikey" "next" - run: name: Test the "forum" application switch @@ -344,7 +344,7 @@ jobs: # Switch next route to current bin/ci-ansible-playbook switch.yml "forum" # Test service switched to the current route - bin/ci-test-service "forum" "collection" "/api/v1/threads?api_key=thisisafakeapikey" + bin/ci-test-route "forum" "collection" "/api/v1/threads?api_key=thisisafakeapikey" # Test the bootstrap playbook on the "edxapp" application # nota bene: we use a real OpenShift cluster installed in CircleCI's VM. @@ -369,8 +369,8 @@ jobs: # Bootstrap app bin/ci-ansible-playbook bootstrap.yml "edxapp,redis" # Test services deployed with the next route - bin/ci-test-service "cms" "Welcome to Your Platform Studio" "/" "next" - bin/ci-test-service "lms" "It works! This is the default homepage for this Open edX instance." "/" "next" + bin/ci-test-route "cms" "Welcome to Your Platform Studio" "/" "next" + bin/ci-test-route "lms" "It works! This is the default homepage for this Open edX instance." "/" "next" - run: name: Test the "edxapp" application switch @@ -378,8 +378,8 @@ jobs: # Switch next route to current bin/ci-ansible-playbook switch.yml "edxapp" # Test service switched to the current route - bin/ci-test-service "cms" "Welcome to Your Platform Studio" - bin/ci-test-service "lms" "It works! This is the default homepage for this Open edX instance." + bin/ci-test-route "cms" "Welcome to Your Platform Studio" + bin/ci-test-route "lms" "It works! This is the default homepage for this Open edX instance." # Test the bootstrap playbook on the "edxec" application # nota bene: we use a real OpenShift cluster installed in CircleCI's VM. @@ -404,14 +404,14 @@ jobs: # Bootstrap edxec bin/ci-ansible-playbook bootstrap.yml "edxec" # Test the service - bin/ci-test-service "edxec" "OK" "/health/" "next" + bin/ci-test-route "edxec" "OK" "/health/" "next" - run: name: Test the "edxec" application switch command: | # Switch next route to current bin/ci-ansible-playbook switch.yml "edxec" - bin/ci-test-service "edxec" "OK" "/health/" + bin/ci-test-route "edxec" "OK" "/health/" # Test the bootstrap playbook on the "marsha" application # nota bene: we use a real OpenShift cluster installed in CircleCI's VM. @@ -436,7 +436,7 @@ jobs: # Bootstrap app bin/ci-ansible-playbook bootstrap.yml "marsha" # Test services deployed with the next route - bin/ci-test-service "marsha" "Api Root" "/api/" "next" + bin/ci-test-route "marsha" "Api Root" "/api/" "next" - run: name: Test the "marsha" application switch @@ -444,7 +444,7 @@ jobs: # Switch next route to current bin/ci-ansible-playbook switch.yml "marsha" # Test service switched to the current route - bin/ci-test-service "marsha" "Api Root" "/api/" + bin/ci-test-route "marsha" "Api Root" "/api/" # Test the bootstrap playbook on the "learninglocker" application. # We also need redis and mailcatcher for this application @@ -468,7 +468,7 @@ jobs: name: Test the "learninglocker" application bootstrapping command: | bin/ci-ansible-playbook bootstrap.yml "redis,mailcatcher,learninglocker" - bin/ci-test-service "learninglocker" "OK" "/api" "next" + bin/ci-test-route "learninglocker" "OK" "/api" "next" - run: name: Test the "learninglocker" application switch @@ -476,7 +476,30 @@ jobs: # Switch next route to current bin/ci-ansible-playbook switch.yml "learninglocker" # Test service switched to the current route - bin/ci-test-service "learninglocker" "OK" "/api" + bin/ci-test-route "learninglocker" "OK" "/api" + + # Test the bootstrap playbook on the "elasticsearch" application. + test-bootstrap-elasticsearch: + machine: + docker_layer_caching: false + + working_directory: ~/fun + + steps: + - checkout + - *attach_workspace + - *docker_load + - *ci_env + - *install_openshift_cluster + - *configure_openshift_cluster + - *run_openshift_cluster + + - run: + name: Test the "elasticsearch" application bootstrapping + command: | + bin/ci-ansible-playbook bootstrap.yml "elasticsearch" + oc project ci-eugene + bin/ci-test-service elasticsearch 9200 "green" /_cluster/health # Test the delete_app tasks for blue-green applications # nota bene: we use a real OpenShift cluster installed in CircleCI's VM. @@ -501,7 +524,7 @@ jobs: # Bootstrap app bin/ci-ansible-playbook bootstrap.yml "richie" # Test service deployed with the next route - bin/ci-test-service "richie" "Django administration" "/en/admin" "next" + bin/ci-test-route "richie" "Django administration" "/en/admin" "next" - run: name: Test "richie"'s next stack substitution (create + delete) @@ -509,7 +532,7 @@ jobs: # Deploy the next stack a second time bin/ci-ansible-playbook deploy.yml "richie" # Test service re-deployed with the next route - bin/ci-test-service "richie" "Django administration" "/en/admin" "next" + bin/ci-test-route "richie" "Django administration" "/en/admin" "next" - run: name: Check that only one pod is running Richie's app @@ -544,7 +567,7 @@ jobs: # Bootstrap app bin/ci-ansible-playbook bootstrap.yml "hello" # Test service deployed with the next route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" "/" "next" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" "/" "next" - run: name: Test "hello"'s switch @@ -552,9 +575,9 @@ jobs: # Switch next route to current bin/ci-ansible-playbook switch.yml "hello" # Test service on the current route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" "/" "current" + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" "/" "current" # Test that the service is not responding on next route - bin/ci-test-service "hello" "Hello OpenShift! by Arnold" "/" "next" && exit 1 || true + bin/ci-test-route "hello" "Hello OpenShift! by Arnold" "/" "next" && exit 1 || true - run: name: Test that a second switch fails to execute with an error @@ -775,6 +798,15 @@ workflows: filters: tags: only: /.*/ + - test-bootstrap-elasticsearch: + requires: + - lint-bash + - lint-docker + - lint-ansible + - lint-plugins + filters: + tags: + only: /.*/ - test-delete-app: requires: - test-bootstrap-richie @@ -812,6 +844,7 @@ workflows: - test-bootstrap-marsha - test-bootstrap-forum - test-bootstrap-learninglocker + - test-bootstrap-elasticsearch - test-redirect - test-delete-app - test-prevent-switch-to-nothing diff --git a/CHANGELOG.md b/CHANGELOG.md index cf1b5e2d7..7a9cbdf60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Versioning](http://semver.org/spec/v2.0.0.html). ### Added +- New application `elasticsearch` deployable _via_ Arnold - Configured nginx cache for statics and media files for the following apps: - `richie` - `marsha` diff --git a/apps/elasticsearch/templates/services/app/configs/elasticsearch.yml.j2 b/apps/elasticsearch/templates/services/app/configs/elasticsearch.yml.j2 new file mode 100644 index 000000000..973aa167d --- /dev/null +++ b/apps/elasticsearch/templates/services/app/configs/elasticsearch.yml.j2 @@ -0,0 +1,23 @@ +cluster.name: {{ elasticsearch_cluster_name }} + +# Bind address (listen to all interfaces) +network.host: "0.0.0.0" + +{% if elasticsearch_image_tag is version('6.0', '<') %} +bootstrap.mlockall: {{ elasticsearch_memory_lock }} +{% else %} +bootstrap.memory_lock: {{ elasticsearch_memory_lock }} +{% endif %} + +# Cluster discovery address, to get the peer list. +# This is a kubernetes service that target every ES running nodes, even if they +# are not ready yet. +discovery.zen.ping.unicast.hosts: elasticsearch-discovery.{{ project_name }}.svc + +discovery.zen.minimum_master_nodes: {{ elasticsearch_minimum_master_nodes }} + +# Security features are disabled by default on ES basic and trial licenses +xpack.security.enabled: false + +# Monitoring is not supported in this arnold application yet +xpack.monitoring.enabled: false diff --git a/apps/elasticsearch/templates/services/app/configs/index-template.json.j2 b/apps/elasticsearch/templates/services/app/configs/index-template.json.j2 new file mode 100644 index 000000000..233c26613 --- /dev/null +++ b/apps/elasticsearch/templates/services/app/configs/index-template.json.j2 @@ -0,0 +1,13 @@ +{ +{% if elasticsearch_image_tag is version('6.0', '<') %} + "template" : "*", +{% else %} + "index_patterns": ["*"], +{% endif %} + "settings" : { + "number_of_shards": {{ elasticsearch_index_default_shards }}, + "number_of_replicas": {{ elasticsearch_index_default_replicas }}, + "index.store.type": "{{ elasticsearch_index_store_type }}", + "index.unassigned.node_left.delayed_timeout": "{{ elasticsearch_index_node_left_delayed_timeout }}" + } +} diff --git a/apps/elasticsearch/templates/services/app/configs/readiness-probe.sh.j2 b/apps/elasticsearch/templates/services/app/configs/readiness-probe.sh.j2 new file mode 100644 index 000000000..54704a8eb --- /dev/null +++ b/apps/elasticsearch/templates/services/app/configs/readiness-probe.sh.j2 @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +set -eo pipefail + +declare -r ES_HOST="127.0.0.1" +declare -i ES_PORT={{ elasticsearch_api_port }} +declare -r ES_STARTED="/tmp/es_started" + +function testStatus() { + status_to_test="${1}" + expected_status="${2}" + + declare -A statuses=( ["red"]=1 ["yellow"]=2 ["green"]=3 ) + + if [[ -z "${status_to_test}" || -z "${statuses[${status_to_test}]}" ]] ; then + echo "Error: unknown status_to_test [${status_to_test}]" 1>&2 + exit 1 + fi + + if [[ -z "${expected_status}" || -z "${statuses[${expected_status}]}" ]]; then + echo "Error: unknown expected_status [${expected_status}]" 1>&2 + exit 2 + fi + + if [ "${statuses[$status_to_test]}" -lt "${statuses[${expected_status}]}" ]; then + echo "Assertion failed: ${status_to_test} < ${expected_status}" + exit 3 + fi +} + +if [ -f "${ES_STARTED}" ]; then + echo -n "Elasticsearch is already running. Checking if API is alive..." + curl -fsSL "http://${ES_HOST}:${ES_PORT}/" > /dev/null + echo "OK" +else + echo "Waiting for elasticsearch cluster to be running and in green state..." + health_status=$( + curl -fsSL "http://${ES_HOST}:${ES_PORT}/_cat/health?h=status" | \ + sed -r 's/^[[:space:]]+|[[:space:]]+$//g' + ) + testStatus "${health_status}" "green" + + echo "Waiting for initializing_shards to be 0" + init_shards=$( + curl -fsSL "http://${ES_HOST}:${ES_PORT}/_cat/health?h=init" | \ + sed -r 's/^[[:space:]]+|[[:space:]]+$//g' + ) + + if [ "${init_shards}" -gt 0 ]; then + echo "Synchronization not ready yet, initializing_shards = ${init_shards}" + exit 4 + fi + + touch "${ES_STARTED}" + + echo "Elasticsearch cluster is up (status = ${health_status})" +fi diff --git a/apps/elasticsearch/templates/services/app/configs/set-index-template.sh.j2 b/apps/elasticsearch/templates/services/app/configs/set-index-template.sh.j2 new file mode 100644 index 000000000..2396d8d2d --- /dev/null +++ b/apps/elasticsearch/templates/services/app/configs/set-index-template.sh.j2 @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -eo pipefail + +declare -i MAX_RETRY=20 +declare -i RETRY_DELAY=5 +declare -i retry=0 + +echo -n "Waiting for ES service to be up." +while ! curl --output /dev/null --silent --max-time 1 --connect-timeout 1 --head --fail "http://elasticsearch.{{ project_name }}.svc:{{ elasticsearch_api_port }}/" +do + echo -n "." + ((retry++)) && ((retry==MAX_RETRY)) && echo "ERROR: timeout" && exit 62 + sleep ${RETRY_DELAY} +done + +curl -fssL \ + -X PUT "http://elasticsearch.{{ project_name }}.svc:{{ elasticsearch_api_port }}/_template/default" \ + -H 'Content-Type: application/json' \ + -d @/usr/local/share/elasticsearch/index-template.json diff --git a/apps/elasticsearch/templates/services/app/dc.yml.j2 b/apps/elasticsearch/templates/services/app/dc.yml.j2 new file mode 100644 index 000000000..5586bab65 --- /dev/null +++ b/apps/elasticsearch/templates/services/app/dc.yml.j2 @@ -0,0 +1,84 @@ +apiVersion: v1 +kind: DeploymentConfig +metadata: + labels: + app: elasticsearch + service: app + version: "{{ elasticsearch_image_tag }}" + type: es-node + name: "elasticsearch-node" + namespace: "{{ project_name }}" +spec: + replicas: {{ elasticsearch_nodes }} + template: + metadata: + labels: + app: elasticsearch + service: app + type: es-node + spec: + strategy: + type: Rolling + rollingParams: + maxUnavailable: 0 + maxSurge: 1 + timeoutSeconds: 3600 + # Prefer running pods on different nodes for redundancy + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: deploymentconfig + operator: In + values: + - "elasticsearch-node" + topologyKey: kubernetes.io/hostname + containers: + - image: {{ elasticsearch_image_name }}:{{ elasticsearch_image_tag }} + name: elasticsearch + ports: + - containerPort: {{ elasticsearch_api_port }} + protocol: TCP + name: "http-port" + - containerPort: {{ elasticsearch_communication_port }} + protocol: TCP + name: "comm-port" + volumeMounts: + - name: elasticsearch-config + mountPath: /usr/share/elasticsearch/config/elasticsearch.yml + subPath: elasticsearch.yml + - name: readiness-probe + mountPath: /usr/local/bin/readiness-probe.sh + subPath: readiness-probe.sh + env: + - name: ES_JAVA_OPTS + value: "{{ elasticsearch_java_opts | join(' ') }}" + readinessProbe: + exec: + command: + - /usr/local/bin/readiness-probe.sh + initialDelaySeconds: 20 + periodSeconds: 5 + livenessProbe: + httpGet: + path: / + port: {{ elasticsearch_api_port }} + initialDelaySeconds: 30 + periodSeconds: 30 + volumes: + - name: elasticsearch-config + configMap: + name: elasticsearch-app-{{ deployment_stamp }} + items: + - key: elasticsearch.yml + path: elasticsearch.yml + - name: readiness-probe + configMap: + name: elasticsearch-app-{{ deployment_stamp }} + defaultMode: 0755 + items: + - key: readiness-probe.sh + path: readiness-probe.sh diff --git a/apps/elasticsearch/templates/services/app/job_set_index_template.yml.j2 b/apps/elasticsearch/templates/services/app/job_set_index_template.yml.j2 new file mode 100644 index 000000000..0cc11a6cb --- /dev/null +++ b/apps/elasticsearch/templates/services/app/job_set_index_template.yml.j2 @@ -0,0 +1,49 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: "es-index-template-{{ job_stamp }}" + namespace: "{{ project_name }}" + labels: + app: elasticsearch + service: app + version: "{{ elasticsearch_image_tag }}" + job_stamp: "{{ job_stamp }}" + job_type: "post" + deployment_stamp: "{{ deployment_stamp }}" +spec: + template: + metadata: + name: "es-index-template-{{ job_stamp }}" + labels: + app: elasticsearch + service: app + version: "{{ elasticsearch_image_tag }}" + deployment_stamp: "{{ deployment_stamp }}" + job_stamp: "{{ job_stamp }}" + spec: + containers: + - name: es-index-template + image: "{{ elasticsearch_image_name }}:{{ elasticsearch_image_tag }}" + command: [ "/usr/local/bin/set-index-template.sh" ] + volumeMounts: + - name: set-index-template + mountPath: /usr/local/bin/set-index-template.sh + subPath: set-index-template.sh + - name: index-template + mountPath: /usr/local/share/elasticsearch/index-template.json + subPath: index-template.json + restartPolicy: Never + volumes: + - name: set-index-template + configMap: + name: elasticsearch-app-{{ deployment_stamp }} + defaultMode: 0755 + items: + - key: set-index-template.sh + path: set-index-template.sh + - name: index-template + configMap: + name: elasticsearch-app-{{ deployment_stamp }} + items: + - key: index-template.json + path: index-template.json diff --git a/apps/elasticsearch/templates/services/app/svc-discovery.yml.j2 b/apps/elasticsearch/templates/services/app/svc-discovery.yml.j2 new file mode 100644 index 000000000..e5be273c6 --- /dev/null +++ b/apps/elasticsearch/templates/services/app/svc-discovery.yml.j2 @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: elasticsearch + service: app + version: "{{ elasticsearch_image_tag }}" + name: elasticsearch-discovery + namespace: "{{ project_name }}" + annotations: + # Deprecated annotation replaced by publishNotReadyAddresses + # Needed to be compatible with openshift < 3.11 + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" +spec: + clusterIP: None + # Required for peer discovery. + # It allows ES nodes to join the cluster and start data synchronization before being declared ready. + publishNotReadyAddresses: true + selector: + app: elasticsearch + service: app + type: es-node + ports: + - name: transport + port: {{ elasticsearch_communication_port }} diff --git a/apps/elasticsearch/templates/services/app/svc.yml.j2 b/apps/elasticsearch/templates/services/app/svc.yml.j2 new file mode 100644 index 000000000..6ef7658d3 --- /dev/null +++ b/apps/elasticsearch/templates/services/app/svc.yml.j2 @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: elasticsearch + service: app + version: "{{ elasticsearch_image_tag }}" + name: elasticsearch + namespace: "{{ project_name }}" +spec: + selector: + app: elasticsearch + service: app + type: es-node + ports: + - name: http + port: {{ elasticsearch_api_port }} + type: ClusterIP diff --git a/apps/elasticsearch/tray.yml b/apps/elasticsearch/tray.yml new file mode 100644 index 000000000..dc0117a7a --- /dev/null +++ b/apps/elasticsearch/tray.yml @@ -0,0 +1,3 @@ +metadata: + name: elasticsearch + version: 6.6.2 diff --git a/apps/elasticsearch/vars/all/main.yml b/apps/elasticsearch/vars/all/main.yml new file mode 100644 index 000000000..ae37b3c0a --- /dev/null +++ b/apps/elasticsearch/vars/all/main.yml @@ -0,0 +1,52 @@ +# -- Docker related configuration + +elasticsearch_image_name: "fundocker/openshift-elasticsearch" +elasticsearch_image_tag: "6.6.2" + +# -- Node specific configuration + +# JVM options +# (-Xms and -Xmx must have the same value or elasticsearch will fail to boot) +elasticsearch_java_opts: + - "-Xms512m" + - "-Xmx512m" + +# If set to true, it prevent any elasticsearch memory from being swapped out. +# It uses mlockall on Linux/Unix systems to try to lock the process address space into RAM +# This is not the only option to disable swap, you can also configure swapiness on each kubernetes node. +elasticsearch_memory_lock: false + +# -- Cluster configuration + +# cluster size (number of pods to start) +elasticsearch_nodes: 3 + +# Minimum number of master eligible nodes a node should "see" in order to win a master election +# (see discovery.zen.minimum_master_nodes setting in ES documentation) +elasticsearch_minimum_master_nodes: 2 + +elasticsearch_cluster_name: "elasticsearch-cluster" +elasticsearch_api_port: 9200 +elasticsearch_communication_port: 9300 + +# -- Default index template +# The values in this section will only affect future creation of indexes. +# If you modify them, they will not have any effect on existing indexes. + +# Number of shards per index +elasticsearch_index_default_shards: 2 + +# Number of replica of each shard +elasticsearch_index_default_replicas: 2 + +# If a node is disconnected, the cluster will wait (default is 1m) before re-assigning shards to other nodes. +# This has an impact on the rolling upgrade process, it will take at least: +# (elasticsearch_nodes * elasticsearch_index_node_left_delayed_timeout) + data synchronization time +# (see index.unassigned.node_left.delayed_timeout setting in ES documentation) +elasticsearch_index_node_left_delayed_timeout: "30s" + + +# Index storage type +# (see index.store.type in ES documentation) +elasticsearch_index_store_type: "niofs" + diff --git a/apps/elasticsearch/vars/settings.yml b/apps/elasticsearch/vars/settings.yml new file mode 100644 index 000000000..ca6144665 --- /dev/null +++ b/apps/elasticsearch/vars/settings.yml @@ -0,0 +1 @@ +is_blue_green_compatible: False diff --git a/bin/ci-test-route b/bin/ci-test-route new file mode 100755 index 000000000..022cf78a3 --- /dev/null +++ b/bin/ci-test-route @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# +# usage: ci-test-route [SERVICE] [CONTENT] [PATH] [PREFIX] + +# First script argument is the application's service name. It defaults to +# 'hello' +service="${1:-hello}" + +# Second script argument is the message to look for in the application's service +# HTTP response. If this message has been found, it means that the application's +# service is up and running, thus validating deployment. It defaults to the +# expected 'hello' service message. +content="${2:-Hello OpenShift! by Arnold}" + +# Third script argument is the url path. It defaults to: "/" +path="${3:-"/"}" + +# Fourth script argument is the prefix used in the url. It defaults to "current". +prefix="${4:-"current"}" + +# Current URL has by definition no prefix, while next and previous URLs are +# sub-domains. Hence, we add the sub-domain dot for next and previous prefixes +# and remove the current prefix for the current URL. +if [[ "${prefix}" != "current" ]]; then + prefix="${prefix}." +else + prefix="" +fi + +# Wait for the application to respond +for try in $(seq 5); do + echo "Testing ${service} application http response ($try)" + curl -vLk --header "Accept: text/html" "https://${prefix}${service}.ci-eugene.${OPENSHIFT_DOMAIN}.nip.io${path}" 2> "/tmp/${service}.err" > "/tmp/${service}.out" + if grep "HTTP/1.1 200 OK" "/tmp/${service}.err" && grep "${content}" "/tmp/${service}.out"; then + exit 0 + fi + sleep 10 +done +exit 1 diff --git a/bin/ci-test-service b/bin/ci-test-service index b8d06f407..89078502c 100755 --- a/bin/ci-test-service +++ b/bin/ci-test-service @@ -1,37 +1,49 @@ #!/usr/bin/env bash # -# usage: ci-test-service [SERVICE] [CONTENT] [PATH] [PREFIX] +# usage: ci-test-service [SERVICE] [PORT] [CONTENT] [PATH] [PREFIX] [PROTOCOL] # First script argument is the application's service name. It defaults to # 'hello' service="${1:-hello}" +# Second script argument is the port number of the service to test +port="${2:-8080}" + # Second script argument is the message to look for in the application's service # HTTP response. If this message has been found, it means that the application's # service is up and running, thus validating deployment. It defaults to the # expected 'hello' service message. -content="${2:-Hello OpenShift! by Arnold}" +content="${3:-Hello OpenShift! by Arnold}" # Third script argument is the url path. It defaults to: "/" -path="${3:-"/"}" +path="${4:-"/"}" # Fourth script argument is the prefix used in the url. It defaults to "current". -prefix="${4:-"current"}" +prefix="${5}" + +# Fifth script argument is the protocol to use with curl (http or https) +protocol=${6:-"http"} # Current URL has by definition no prefix, while next and previous URLs are # sub-domains. Hence, we add the sub-domain dot for next and previous prefixes # and remove the current prefix for the current URL. -if [[ "${prefix}" != "current" ]]; then - prefix="${prefix}." -else - prefix="" +if [[ -n "${prefix}" ]]; then + service="${service}-${prefix}" +fi + +echo -n "Getting ClusterIP for service ${service}..." +service_ip=$(oc get "svc/${service}" -o jsonpath='{.spec.clusterIP}') +if [ -z "${service_ip}" ]; then + echo "ERROR : Unable to get service IP" + exit 1 fi +echo "[${service_ip}]"; -# Wait for the application to respond +# Wait for the service to respond for try in $(seq 5); do - echo "Testing ${service} application http response ($try)" - curl -vLk --header "Accept: text/html" "https://${prefix}${service}.ci-eugene.${OPENSHIFT_DOMAIN}.nip.io${path}" 2> "/tmp/${service}.err" > "/tmp/${service}.out" - if grep "HTTP/1.1 200 OK" "/tmp/${service}.err" && grep "${content}" "/tmp/${service}.out"; then + echo "Testing ${service_ip} on port ${port} ($try)" + curl -vLk --header "Accept: text/html" "${protocol}://${service_ip}:${port}${path}" 2> "/tmp/svc-${service}.err" > "/tmp/svc-${service}.out" + if grep "HTTP/1.1 200 OK" "/tmp/svc-${service}.err" && grep "${content}" "/tmp/svc-${service}.out"; then exit 0 fi sleep 10 diff --git a/group_vars/customer/eugene/development/main.yml b/group_vars/customer/eugene/development/main.yml index 0ac57857f..4e5f42082 100644 --- a/group_vars/customer/eugene/development/main.yml +++ b/group_vars/customer/eugene/development/main.yml @@ -23,6 +23,7 @@ apps: - name: redis - name: hello - name: edxec + - name: elasticsearch # Install a custom theme for edxapp-lms edxapp_theme_url: "https://github.com/raccoongang/themes_for_themex.io" diff --git a/group_vars/customer/eugene/main.yml b/group_vars/customer/eugene/main.yml index b31cb2112..175a20eda 100644 --- a/group_vars/customer/eugene/main.yml +++ b/group_vars/customer/eugene/main.yml @@ -9,3 +9,10 @@ apps: # Marsha # We don't want to require an AWS SSH key for testing marsha_should_sign_requests: false + + +# Elasticsearch +# Limit memory usage +elasticsearch_java_opts: + - "-Xms64m" + - "-Xmx64m" diff --git a/group_vars/env_type/ci.yml b/group_vars/env_type/ci.yml index 26425cad2..d5c1d3137 100644 --- a/group_vars/env_type/ci.yml +++ b/group_vars/env_type/ci.yml @@ -11,6 +11,7 @@ internal_docker_registry: "172.30.1.1:5000" apps: - name: edxapp - name: edxec + - name: elasticsearch - name: forum - name: hello - name: learninglocker diff --git a/group_vars/env_type/development.yml b/group_vars/env_type/development.yml index 00a1001a5..a6f0fb4d8 100644 --- a/group_vars/env_type/development.yml +++ b/group_vars/env_type/development.yml @@ -10,6 +10,7 @@ internal_docker_registry: "172.30.1.1:5000" apps: - name: edxapp - name: edxec + - name: elasticsearch - name: hello - name: learninglocker - name: mailcatcher