diff --git a/README.md b/README.md index 49470dc..d54a5bb 100644 --- a/README.md +++ b/README.md @@ -196,11 +196,11 @@ Add new variable to `deploy/deploy-project.sh` and specify your redis version ... ``` -### Enable Horizontal pod autoscaling +### Disable Horizontal pod autoscaling -Add new variables to `deploy/deploy-project.sh` to enable pod autoscaling: +Add new variables to `deploy/deploy-project.sh` to disable pod autoscaling: -- Enable this functionality: +- Disable this functionality: ```diff ... function deploy() { @@ -209,7 +209,7 @@ Add new variables to `deploy/deploy-project.sh` to enable pod autoscaling: ... ) - + ENABLE_AUTOSCALING=true + + ENABLE_AUTOSCALING=false ... ``` - If you need more replicas, then you can adjust those variables (default values are set to 2): diff --git a/deploy/parts/autoscaling.sh b/deploy/parts/autoscaling.sh index bd925a2..dd16ac2 100644 --- a/deploy/parts/autoscaling.sh +++ b/deploy/parts/autoscaling.sh @@ -1,29 +1,34 @@ #!/bin/bash -e -echo -n "Prepare Autoscaling " +patch_rollout() { + local file="$1" min_replicas="$2" + + if (( min_replicas >= 4 )); then + yq e -i ".spec.strategy.rollingUpdate.maxUnavailable=25%" "$file" + fi + + if (( min_replicas >= 6 )); then + yq e -i ".spec.strategy.rollingUpdate.maxSurge=25%" "$file" + fi +} assertVariable "BASE_PATH" assertVariable "CONFIGURATION_TARGET_PATH" +assertVariable "RUNNING_PRODUCTION" -if [ -z ${ENABLE_AUTOSCALING} ]; then - ENABLE_AUTOSCALING=false -fi +if [[ "${ENABLE_AUTOSCALING:-true}" == "true" ]]; then + echo -n "Prepare Autoscaling " -if [ ${ENABLE_AUTOSCALING} = true ]; then - if [ -z ${MIN_PHP_FPM_REPLICAS} ]; then - MIN_PHP_FPM_REPLICAS=2 - fi + MIN_PHP_FPM_REPLICAS="${MIN_PHP_FPM_REPLICAS:-2}" + MAX_PHP_FPM_REPLICAS="${MAX_PHP_FPM_REPLICAS:-3}" + MIN_STOREFRONT_REPLICAS="${MIN_STOREFRONT_REPLICAS:-2}" + MAX_STOREFRONT_REPLICAS="${MAX_STOREFRONT_REPLICAS:-3}" - if [ -z ${MAX_PHP_FPM_REPLICAS} ]; then - MAX_PHP_FPM_REPLICAS=3 - fi - - if [ -z ${MIN_STOREFRONT_REPLICAS} ]; then + if [[ "${RUNNING_PRODUCTION}" -eq 0 || "${DOWNSCALE_RESOURCE:-0}" -eq 1 ]]; then + MIN_PHP_FPM_REPLICAS=2 + MAX_PHP_FPM_REPLICAS=2 MIN_STOREFRONT_REPLICAS=2 - fi - - if [ -z ${MAX_STOREFRONT_REPLICAS} ]; then - MAX_STOREFRONT_REPLICAS=3 + MAX_STOREFRONT_REPLICAS=2 fi yq e -i ".spec.minReplicas=${MIN_PHP_FPM_REPLICAS}" "${CONFIGURATION_TARGET_PATH}/horizontalPodAutoscaler.yaml" @@ -31,7 +36,16 @@ if [ ${ENABLE_AUTOSCALING} = true ]; then yq e -i ".spec.minReplicas=${MIN_STOREFRONT_REPLICAS}" "${CONFIGURATION_TARGET_PATH}/horizontalStorefrontAutoscaler.yaml" yq e -i ".spec.maxReplicas=${MAX_STOREFRONT_REPLICAS}" "${CONFIGURATION_TARGET_PATH}/horizontalStorefrontAutoscaler.yaml" -fi + patch_rollout "${CONFIGURATION_TARGET_PATH}/deployments/webserver-php-fpm.yaml" "${MIN_PHP_FPM_REPLICAS}" + patch_rollout "${CONFIGURATION_TARGET_PATH}/deployments/storefront.yaml" "${MIN_STOREFRONT_REPLICAS}" + + yq e -i ' + .resources += [ + "../../horizontalPodAutoscaler.yaml", + "../../horizontalStorefrontAutoscaler.yaml" + ] + ' "${CONFIGURATION_TARGET_PATH}/kustomize/webserver/kustomization.yaml" -echo -e "[${GREEN}OK${NO_COLOR}]" + echo -e "[${GREEN}OK${NO_COLOR}]" +fi diff --git a/deploy/parts/deploy.sh b/deploy/parts/deploy.sh index 9f3265c..4af6c86 100644 --- a/deploy/parts/deploy.sh +++ b/deploy/parts/deploy.sh @@ -11,7 +11,6 @@ assertVariable "DEPLOY_REGISTER_USER" assertVariable "DEPLOY_REGISTER_PASSWORD" assertVariable "BASIC_AUTH_PATH" -assertVariable "ENABLE_AUTOSCALING" assertVariable "RUNNING_PRODUCTION" FIRST_DEPLOY_LOAD_DEMO_DATA=${FIRST_DEPLOY_LOAD_DEMO_DATA:-0} @@ -26,11 +25,7 @@ echo -n " Delete secret for docker registry " runCommand "SKIP" "kubectl delete secret dockerregistry -n ${PROJECT_NAME}" echo -n " Create new secret for docker registry " -if [ "${GCLOUD_DEPLOY}" = "true" ]; then - runCommand "ERROR" "kubectl create secret docker-registry dockerregistry --docker-server=eu.gcr.io --docker-username _json_key --docker-email ${GCLOUD_CONTAINER_REGISTRY_EMAIL} --docker-password='${GCLOUD_CONTAINER_REGISTRY_ACCOUNT}' -n ${PROJECT_NAME}" -else - runCommand "ERROR" "kubectl create secret docker-registry dockerregistry --docker-server=${CI_REGISTRY} --docker-username=${DEPLOY_REGISTER_USER} --docker-password=${DEPLOY_REGISTER_PASSWORD} -n ${PROJECT_NAME}" -fi +runCommand "ERROR" "kubectl create secret docker-registry dockerregistry --docker-server=${CI_REGISTRY} --docker-username=${DEPLOY_REGISTER_USER} --docker-password=${DEPLOY_REGISTER_PASSWORD} -n ${PROJECT_NAME}" if [ ${RUNNING_PRODUCTION} -eq "0" ] || [ ${#FORCE_HTTP_AUTH_IN_PRODUCTION[@]} -ne "0" ]; then echo -n " Create or update secret for http auth " @@ -51,14 +46,11 @@ fi if [ "${RUNNING_PRODUCTION}" -eq "0" ] || [ "${DOWNSCALE_RESOURCE:-0}" -eq "1" ]; then echo -n " Replace pods CPU requests to minimum (for Devel cluster only) " - yq e -i '.spec.template.spec.containers[0].resources.requests.cpu = "0.01"' "${CONFIGURATION_TARGET_PATH}/deployments/storefront.yaml" - yq e -i '.spec.template.spec.containers[0].resources.requests.cpu = "0.01"' "${CONFIGURATION_TARGET_PATH}/deployments/webserver-php-fpm.yaml" - yq e -i '.spec.template.spec.containers[1].resources.requests.cpu = "0.01"' "${CONFIGURATION_TARGET_PATH}/deployments/webserver-php-fpm.yaml" - yq e -i '.spec.template.spec.containers[1].resources.requests.cpu = "0.01"' "${CONFIGURATION_TARGET_PATH}/deployments/redis.yaml" - yq e -i '.spec.template.spec.containers[0].resources.requests.cpu = "0.01"' "${CONFIGURATION_TARGET_PATH}/deployments/rabbitmq.yaml" + yq e -i '.spec.template.spec.containers[0].resources.requests.cpu = "0.1"' "${CONFIGURATION_TARGET_PATH}/deployments/storefront.yaml" + yq e -i '.spec.template.spec.containers[0].resources.requests.cpu = "0.1"' "${CONFIGURATION_TARGET_PATH}/deployments/webserver-php-fpm.yaml" yq e -i '.spec.template.spec.containers[0].resources.requests.memory = "100Mi"' "${CONFIGURATION_TARGET_PATH}/deployments/webserver-php-fpm.yaml" - yq e -i '.spec.template.spec.containers[1].resources.requests.memory = "100Mi"' "${CONFIGURATION_TARGET_PATH}/deployments/redis.yaml" + yq e -i '.spec.template.spec.containers[0].resources.requests.memory = "100Mi"' "${CONFIGURATION_TARGET_PATH}/deployments/redis.yaml" echo -e "[${GREEN}OK${NO_COLOR}]" else @@ -77,14 +69,10 @@ else fi fi -DEPLOYED_CRON_POD=$(kubectl get pods --namespace=${PROJECT_NAME} --field-selector=status.phase=Running -l app=cron -o=jsonpath='{.items[?(@.status.containerStatuses[0].state.running)].metadata.name}') || true - -if [[ -n ${DEPLOYED_CRON_POD} ]]; then - echo -n "Lock crons to prevent run next iteration " - runCommand "ERROR" "kubectl exec -t --namespace=${PROJECT_NAME} ${DEPLOYED_CRON_POD} -- bash -c \"./phing -S cron-lock > /dev/null 2>&1 & disown\"" - - echo -n "Waiting until all cron instances are done " - runCommand "ERROR" "kubectl exec --namespace=${PROJECT_NAME} ${DEPLOYED_CRON_POD} -- ./phing -S cron-watch" +if kubectl get deployment/cron --namespace="${PROJECT_NAME}" >/dev/null 2>&1; then + echo -n "Waiting until all cron instances are done and stop cron" + runCommand "ERROR" "kubectl scale deployment/cron --namespace=${PROJECT_NAME} --replicas=0" + runCommand "ERROR" "kubectl rollout status deployment/cron --namespace=${PROJECT_NAME} --timeout=60m" fi echo "Migrate Application (database migrations, elasticsearch migrations, ...):" @@ -130,7 +118,7 @@ if [ ${MIGRATION_COMPLETE_EXIT_CODE} -eq 1 ]; then echo -e "[${RED}ERROR${NO_COLOR}]" echo -n "Restore previous cron container " - runCommand "SKIP" "kubectl delete pod --namespace=${PROJECT_NAME} ${DEPLOYED_CRON_POD}" + runCommand "SKIP" "kubectl scale deployment/cron --namespace=${PROJECT_NAME} --replicas=1" RUNNING_WEBSERVER_PHP_FPM_POD=$(kubectl get pods --namespace=${PROJECT_NAME} --field-selector=status.phase=Running -l app=webserver-php-fpm -o=jsonpath='{.items[0].metadata.name}') @@ -151,9 +139,6 @@ else kubectl logs job/migrate-application --namespace=${PROJECT_NAME} echo -e "section_end:`date +%s`:migrate_application_logs_section\r\e[0K" echo "" - - echo -n "Deploy new cron container " - runCommand "ERROR" "kustomize build --load_restrictor none \"${CONFIGURATION_TARGET_PATH}/kustomize/cron\" | kubectl apply -f -" fi echo "Deploy new Webserver and PHP-FPM container:" @@ -169,40 +154,12 @@ if [ $DISPLAY_FINAL_CONFIGURATION -eq "1" ]; then echo "" fi -if [ ${ENABLE_AUTOSCALING} = true ]; then - echo -n " Delete previous Horizontal pod autoscaler for Backend " - runCommand "SKIP" "kubectl delete hpa webserver-php-fpm --namespace=${PROJECT_NAME}" - - echo -n " Delete previous Horizontal pod autoscaler for Storefront " - runCommand "SKIP" "kubectl delete hpa storefront --namespace=${PROJECT_NAME}" -fi - echo -n " Deploy Webserver and PHP-FPM container with Storefront" runCommand "ERROR" "kustomize build --load_restrictor none \"${CONFIGURATION_TARGET_PATH}/kustomize/webserver\" | kubectl apply -f -" echo -n " Waiting for start new PHP-FPM and Storefront container (In case of fail you need to manually check what is state of application)" runCommand "ERROR" "kubectl rollout status --namespace=${PROJECT_NAME} deployment/webserver-php-fpm deployment/storefront --watch" -if [ ${ENABLE_AUTOSCALING} = true ]; then - echo -n " Deploy Horizontal pod autoscaler for Backend " - - if [ ${RUNNING_PRODUCTION} -eq "0" ]; then - yq e -i '.spec.minReplicas = 2' "${CONFIGURATION_TARGET_PATH}/horizontalPodAutoscaler.yaml" - yq e -i '.spec.maxReplicas = 2' "${CONFIGURATION_TARGET_PATH}/horizontalPodAutoscaler.yaml" - fi - - runCommand "ERROR" "kubectl apply -f ${CONFIGURATION_TARGET_PATH}/horizontalPodAutoscaler.yaml" - - echo -n " Deploy Horizontal pod autoscaler for Storefront " - - if [ ${RUNNING_PRODUCTION} -eq "0" ]; then - yq e -i '.spec.minReplicas = 2' "${CONFIGURATION_TARGET_PATH}/horizontalStorefrontAutoscaler.yaml" - yq e -i '.spec.maxReplicas = 2' "${CONFIGURATION_TARGET_PATH}/horizontalStorefrontAutoscaler.yaml" - fi - - runCommand "ERROR" "kubectl apply -f ${CONFIGURATION_TARGET_PATH}/horizontalStorefrontAutoscaler.yaml" -fi - RUNNING_WEBSERVER_PHP_FPM_POD=$(kubectl get pods --namespace=${PROJECT_NAME} --field-selector=status.phase=Running -l app=webserver-php-fpm -o=jsonpath='{.items[?(@.status.containerStatuses[0].state.running)].metadata.name}') echo -n "Disable maintenance page " diff --git a/deploy/parts/environment-variables.sh b/deploy/parts/environment-variables.sh index da3d96c..40baacf 100644 --- a/deploy/parts/environment-variables.sh +++ b/deploy/parts/environment-variables.sh @@ -36,6 +36,14 @@ for key in "${!ENVIRONMENT_VARIABLES[@]}"; do } " "${CONFIGURATION_TARGET_PATH}/deployments/webserver-php-fpm.yaml" + # Webserver PHP-FPM warmup container + yq e -i " + .spec.template.spec.initContainers[1].env[${ITERATOR}] = { + \"name\": \"${key}\", + \"value\": \"${ENVIRONMENT_VARIABLES[$key]}\" + } + " "${CONFIGURATION_TARGET_PATH}/deployments/webserver-php-fpm.yaml" + # Cron deployment yq e -i " .spec.template.spec.containers[0].env[${ITERATOR}] = { diff --git a/docs/deploy-project.sh b/docs/deploy-project.sh index 21e2cfc..38ec18b 100644 --- a/docs/deploy-project.sh +++ b/docs/deploy-project.sh @@ -11,8 +11,6 @@ function deploy() { DOMAIN_HOSTNAME_2 ) - ENABLE_AUTOSCALING=true - declare -A ENVIRONMENT_VARIABLES=( ["APP_SECRET"]=${APP_SECRET} ["DATABASE_HOST"]=${POSTGRES_DATABASE_IP_ADDRESS} diff --git a/kubernetes/configmap/nginx.yaml b/kubernetes/configmap/nginx.yaml index 8bf897e..9838510 100644 --- a/kubernetes/configmap/nginx.yaml +++ b/kubernetes/configmap/nginx.yaml @@ -73,8 +73,15 @@ data: root /var/www/html/web; location /health { - stub_status on; access_log off; + + include fastcgi_params; + fastcgi_read_timeout 3s; + fastcgi_param SCRIPT_FILENAME /ping; + fastcgi_param SCRIPT_NAME /ping; + fastcgi_param REQUEST_METHOD GET; + + fastcgi_pass php-upstream; } } diff --git a/kubernetes/configmap/production-php-fpm.yaml b/kubernetes/configmap/production-php-fpm.yaml index 22e11fd..89eb840 100644 --- a/kubernetes/configmap/production-php-fpm.yaml +++ b/kubernetes/configmap/production-php-fpm.yaml @@ -15,6 +15,8 @@ data: [www] listen = 127.0.0.1:9000 + ping.path = /ping + ping.response = pong pm = dynamic pm.max_children = 20 diff --git a/kubernetes/deployments/cron.yaml b/kubernetes/deployments/cron.yaml index eaf8ec7..7467f2e 100644 --- a/kubernetes/deployments/cron.yaml +++ b/kubernetes/deployments/cron.yaml @@ -5,13 +5,9 @@ metadata: labels: app: cron spec: - progressDeadlineSeconds: 1500 replicas: 1 strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - type: RollingUpdate + type: Recreate selector: matchLabels: app: cron @@ -25,6 +21,7 @@ spec: labels: app: cron spec: + terminationGracePeriodSeconds: 3000 tolerations: - key: "workload" operator: "Equal" @@ -38,8 +35,7 @@ spec: matchExpressions: - key: workload operator: In - values: - - background + values: ["background"] volumes: - name: domains-urls configMap: @@ -61,14 +57,30 @@ spec: runAsUser: 0 imagePullPolicy: IfNotPresent workingDir: /var/www/html - command: ["/bin/sh","-c"] - args: ["cd /var/www/html && ./phing warmup > /dev/null && rm -rf /tmp/log-pipe && mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe && crontab -u root /var/spool/cron/template && { crond || cron; } && stdbuf -o0 tail -n +1 -f /tmp/log-pipe"] + command: ["/bin/sh","-lc"] + args: + - > + ./phing warmup > /dev/null + + # FIFO for logs + rm -f /tmp/log-pipe && mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe + + # crontab + crontab -u root /var/spool/cron/template + + # run on backround + stdbuf -o0 tail -n +1 -f /tmp/log-pipe & + + exec crond -f || exec cron -f lifecycle: preStop: exec: command: - - sleep - - '5' + - /bin/sh + - -lc + - | + ( ./bin/console deploy:cron:lock > /tmp/cron-lock.log 2>&1 || true ) & + ./bin/console deploy:cron:watch || true volumeMounts: - name: domains-urls mountPath: /var/www/html/{{DOMAINS_URLS_FILEPATH}} diff --git a/kubernetes/deployments/rabbitmq.yaml b/kubernetes/deployments/rabbitmq.yaml index c2b9891..42dbe59 100644 --- a/kubernetes/deployments/rabbitmq.yaml +++ b/kubernetes/deployments/rabbitmq.yaml @@ -5,6 +5,10 @@ metadata: spec: serviceName: rabbitmq replicas: 1 + updateStrategy: + type: RollingUpdate + rollingUpdate: + partition: 0 selector: matchLabels: app: rabbitmq @@ -30,6 +34,9 @@ spec: image: rabbitmq:4.1-management-alpine ports: - name: rabbitmq + containerPort: 5672 + protocol: TCP + - name: rabbitmq-management containerPort: 15672 protocol: TCP - name: exporter @@ -40,12 +47,37 @@ spec: value: "{{RABBITMQ_DEFAULT_USER}}" - name: RABBITMQ_DEFAULT_PASS value: "{{RABBITMQ_DEFAULT_PASS}}" + lifecycle: + preStop: + exec: + command: [ "sh", "-c", "rabbitmqctl stop_app && sleep 5" ] resources: requests: cpu: "20m" + memory: "256Mi" + limits: + memory: "512Mi" + startupProbe: + exec: + command: [ "rabbitmq-diagnostics", "ping" ] + failureThreshold: 30 + periodSeconds: 10 + livenessProbe: + exec: + command: ["rabbitmq-diagnostics", "ping"] + periodSeconds: 30 + timeoutSeconds: 15 + failureThreshold: 5 + readinessProbe: + exec: + command: [ "rabbitmq-diagnostics", "-q", "check_running" ] + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 volumeMounts: - name: rabbitmq-data mountPath: /var/lib/rabbitmq + terminationGracePeriodSeconds: 90 imagePullSecrets: - name: dockerregistry volumeClaimTemplates: diff --git a/kubernetes/deployments/redis.yaml b/kubernetes/deployments/redis.yaml index 715b7dc..d5f4aaf 100644 --- a/kubernetes/deployments/redis.yaml +++ b/kubernetes/deployments/redis.yaml @@ -27,19 +27,6 @@ spec: name: redis defaultMode: 0755 containers: - - name: redis-exporter - image: "oliver006/redis_exporter" - imagePullPolicy: Always - ports: - - name: exporter - containerPort: 9121 - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - name: redis image: "{{REDIS_VERSION}}" ports: @@ -76,3 +63,16 @@ spec: requests: memory: "2500Mi" cpu: "100m" + - name: redis-exporter + image: "oliver006/redis_exporter" + imagePullPolicy: Always + ports: + - name: exporter + containerPort: 9121 + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi diff --git a/kubernetes/deployments/storefront.yaml b/kubernetes/deployments/storefront.yaml index 000a70f..708d8c2 100644 --- a/kubernetes/deployments/storefront.yaml +++ b/kubernetes/deployments/storefront.yaml @@ -4,6 +4,11 @@ metadata: name: storefront spec: replicas: 1 + strategy: + rollingUpdate: + maxSurge: 50% + maxUnavailable: 0 + type: RollingUpdate selector: matchLabels: app: storefront @@ -39,29 +44,35 @@ spec: lifecycle: preStop: exec: - command: - - sleep - - '10' + command: ["/bin/sh","-lc","sleep 10"] resources: limits: memory: "1.5Gi" requests: cpu: "500m" memory: "800Mi" + startupProbe: + httpGet: + path: /api/health + port: 3000 + periodSeconds: 2 + timeoutSeconds: 2 + failureThreshold: 60 livenessProbe: httpGet: path: /api/health port: 3000 - initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 readinessProbe: httpGet: path: /api/health port: 3000 initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 3 + timeoutSeconds: 2 + failureThreshold: 1 terminationGracePeriodSeconds: 60 imagePullSecrets: - name: dockerregistry diff --git a/kubernetes/deployments/webserver-php-fpm.yaml b/kubernetes/deployments/webserver-php-fpm.yaml index a3e756c..98ee714 100644 --- a/kubernetes/deployments/webserver-php-fpm.yaml +++ b/kubernetes/deployments/webserver-php-fpm.yaml @@ -9,7 +9,7 @@ spec: replicas: 1 strategy: rollingUpdate: - maxSurge: 1 + maxSurge: 50% maxUnavailable: 0 type: RollingUpdate selector: @@ -83,21 +83,36 @@ spec: - name: domains-urls mountPath: /var/www/html/{{DOMAINS_URLS_FILEPATH}} subPath: "{{DOMAINS_URLS_FILENAME}}" + - name: warmup + image: "{{TAG}}" + command: ["/var/www/html/phing", "-S", "warmup"] + volumeMounts: + - name: source-codes + mountPath: /var/www/html + - name: domains-urls + mountPath: /var/www/html/{{DOMAINS_URLS_FILEPATH}} + subPath: "{{DOMAINS_URLS_FILENAME}}" containers: - image: "{{TAG}}" name: php-fpm imagePullPolicy: IfNotPresent workingDir: /var/www/html lifecycle: - postStart: - exec: - command: ["/var/www/html/phing", "-S", "warmup"] preStop: exec: - command: - - sh - - '-c' - - sleep 10 && kill -SIGQUIT 1 + command: ["/bin/sh","-lc","sleep 10; kill -QUIT 1 || true"] + livenessProbe: + tcpSocket: + port: 9000 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 2 + readinessProbe: + tcpSocket: + port: 9000 + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 volumeMounts: - name: source-codes mountPath: /var/www/html @@ -125,20 +140,24 @@ spec: ports: - containerPort: 8080 name: http + - containerPort: 80 + name: health livenessProbe: - initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 httpGet: path: /health - port: 80 + port: health + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 6 readinessProbe: httpGet: path: /health - port: 80 - initialDelaySeconds: 5 + port: health + initialDelaySeconds: 2 periodSeconds: 5 - timeoutSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 3 volumeMounts: - name: nginx-default-config mountPath: /etc/nginx/nginx.conf diff --git a/kubernetes/horizontalPodAutoscaler.yaml b/kubernetes/horizontalPodAutoscaler.yaml index 3a22f50..02551c8 100644 --- a/kubernetes/horizontalPodAutoscaler.yaml +++ b/kubernetes/horizontalPodAutoscaler.yaml @@ -2,7 +2,6 @@ apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: webserver-php-fpm - namespace: "{{PROJECT_NAME}}" spec: scaleTargetRef: apiVersion: apps/v1 @@ -10,6 +9,27 @@ spec: name: webserver-php-fpm minReplicas: 2 maxReplicas: 2 + behavior: + scaleUp: + stabilizationWindowSeconds: 60 + selectPolicy: Max + policies: + - type: Pods + value: 2 + periodSeconds: 60 + - type: Percent + value: 50 + periodSeconds: 60 + scaleDown: + stabilizationWindowSeconds: 600 + selectPolicy: Max + policies: + - type: Pods + value: 1 + periodSeconds: 60 + - type: Percent + value: 30 + periodSeconds: 60 metrics: - type: ContainerResource containerResource: diff --git a/kubernetes/horizontalStorefrontAutoscaler.yaml b/kubernetes/horizontalStorefrontAutoscaler.yaml index 6da411e..86164c5 100644 --- a/kubernetes/horizontalStorefrontAutoscaler.yaml +++ b/kubernetes/horizontalStorefrontAutoscaler.yaml @@ -2,7 +2,6 @@ apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: storefront - namespace: "{{PROJECT_NAME}}" spec: scaleTargetRef: apiVersion: apps/v1 @@ -10,6 +9,27 @@ spec: name: storefront minReplicas: 2 maxReplicas: 2 + behavior: + scaleUp: + stabilizationWindowSeconds: 60 + selectPolicy: Max + policies: + - type: Pods + value: 2 + periodSeconds: 60 + - type: Percent + value: 50 + periodSeconds: 60 + scaleDown: + stabilizationWindowSeconds: 600 + selectPolicy: Max + policies: + - type: Pods + value: 1 + periodSeconds: 60 + - type: Percent + value: 30 + periodSeconds: 60 metrics: - type: Resource resource: diff --git a/kubernetes/kustomize/cron/kustomization.yaml b/kubernetes/kustomize/cron/kustomization.yaml deleted file mode 100644 index 6a91ca1..0000000 --- a/kubernetes/kustomize/cron/kustomization.yaml +++ /dev/null @@ -1,10 +0,0 @@ -resources: - - ../../namespace.yaml - - ../../deployments/cron.yaml - - ../../configmap/cron-env.yaml - - ../../configmap/cron-list.yaml -namespace: "{{PROJECT_NAME}}" -configMapGenerator: - - name: domains-urls - files: - - ../../../../../{{DOMAINS_URLS_FILEPATH}} diff --git a/kubernetes/kustomize/migrate-application/continuous-deploy/kustomization.yaml b/kubernetes/kustomize/migrate-application/continuous-deploy/kustomization.yaml index a89a153..4228f6e 100644 --- a/kubernetes/kustomize/migrate-application/continuous-deploy/kustomization.yaml +++ b/kubernetes/kustomize/migrate-application/continuous-deploy/kustomization.yaml @@ -1,7 +1,6 @@ resources: - ../../../deployments/redis.yaml - ../../../services/redis.yaml - - ../../../namespace.yaml - ../../../configmap/redis.yaml - ../../../configmap/redis-health.yaml - ../../../deployments/rabbitmq.yaml diff --git a/kubernetes/kustomize/migrate-application/first-deploy-with-demo-data/kustomization.yaml b/kubernetes/kustomize/migrate-application/first-deploy-with-demo-data/kustomization.yaml index a89a153..4228f6e 100644 --- a/kubernetes/kustomize/migrate-application/first-deploy-with-demo-data/kustomization.yaml +++ b/kubernetes/kustomize/migrate-application/first-deploy-with-demo-data/kustomization.yaml @@ -1,7 +1,6 @@ resources: - ../../../deployments/redis.yaml - ../../../services/redis.yaml - - ../../../namespace.yaml - ../../../configmap/redis.yaml - ../../../configmap/redis-health.yaml - ../../../deployments/rabbitmq.yaml diff --git a/kubernetes/kustomize/migrate-application/first-deploy/kustomization.yaml b/kubernetes/kustomize/migrate-application/first-deploy/kustomization.yaml index a89a153..4228f6e 100644 --- a/kubernetes/kustomize/migrate-application/first-deploy/kustomization.yaml +++ b/kubernetes/kustomize/migrate-application/first-deploy/kustomization.yaml @@ -1,7 +1,6 @@ resources: - ../../../deployments/redis.yaml - ../../../services/redis.yaml - - ../../../namespace.yaml - ../../../configmap/redis.yaml - ../../../configmap/redis-health.yaml - ../../../deployments/rabbitmq.yaml diff --git a/kubernetes/kustomize/webserver/kustomization.yaml b/kubernetes/kustomize/webserver/kustomization.yaml index 50b7351..395d313 100644 --- a/kubernetes/kustomize/webserver/kustomization.yaml +++ b/kubernetes/kustomize/webserver/kustomization.yaml @@ -3,10 +3,12 @@ resources: - ../../services/webserver-php-fpm.yaml - ../../deployments/storefront.yaml - ../../services/storefront.yaml - - ../../namespace.yaml + - ../../deployments/cron.yaml - ../../configmap/nginx.yaml - ../../configmap/production-php-fpm.yaml - ../../configmap/production-php-opcache.yaml + - ../../configmap/cron-env.yaml + - ../../configmap/cron-list.yaml - ../../ingress/ingress-rabbitmq.yaml namespace: "{{PROJECT_NAME}}" configMapGenerator: diff --git a/kubernetes/namespace.yaml b/kubernetes/namespace.yaml deleted file mode 100644 index 74708ba..0000000 --- a/kubernetes/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "{{PROJECT_NAME}}" diff --git a/tests/run-tests.sh b/tests/run-tests.sh index 33e732e..314a3ee 100755 --- a/tests/run-tests.sh +++ b/tests/run-tests.sh @@ -171,11 +171,6 @@ build_outputs() { build_kustomize "${config_path}/kustomize/cron" "${output_dir}/cron.yaml" || true fi - # Copy individual files that aren't built by kustomize - cp "${config_path}/horizontalPodAutoscaler.yaml" "${output_dir}/" 2>/dev/null || true - cp "${config_path}/horizontalStorefrontAutoscaler.yaml" "${output_dir}/" 2>/dev/null || true - cp "${config_path}/namespace.yaml" "${output_dir}/" 2>/dev/null || true - echo "$output_dir" } diff --git a/tests/scenarios/basic-production/deploy-project.sh b/tests/scenarios/basic-production/deploy-project.sh index 65c8654..4eb8fde 100644 --- a/tests/scenarios/basic-production/deploy-project.sh +++ b/tests/scenarios/basic-production/deploy-project.sh @@ -5,7 +5,6 @@ source "$(dirname "$0")/../../lib/scenario-base.sh" # Scenario-specific configuration DOMAINS=(DOMAIN_HOSTNAME_1 DOMAIN_HOSTNAME_2) export RUNNING_PRODUCTION=1 -ENABLE_AUTOSCALING=true declare -A CRON_INSTANCES=( ["cron"]='*/5 * * * *' diff --git a/tests/scenarios/basic-production/expected/cron.yaml b/tests/scenarios/basic-production/expected/cron.yaml deleted file mode 100644 index 6d85982..0000000 --- a/tests/scenarios/basic-production/expected/cron.yaml +++ /dev/null @@ -1,182 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 -data: - .project_env.sh: | - export ELASTICSEARCH_HOST='http://elasticsearch:9200' - export TRUSTED_PROXY='10.0.0.0/8' - export DATABASE_NAME='myproject-production' - export S3_ENDPOINT='https://s3.example.com' - export MAILER_FORCE_WHITELIST='false' - export DATABASE_USER='myproject-production' - export DATABASE_PORT='5432' - export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' - export REDIS_PREFIX='myproject-production' - export DATABASE_PASSWORD='test-db-password' - export DATABASE_HOST='10.0.0.100' - export ELASTIC_SEARCH_INDEX_PREFIX='myproject-production' - export S3_SECRET='test-s3-secret' - export MAILER_DSN='smtp://mailhog:1025' - export S3_BUCKET_NAME='myproject-production' - export S3_ACCESS_KEY='myproject-production' - export APP_SECRET='test-app-secret-key' -kind: ConfigMap -metadata: - name: cron-env - namespace: myproject-production ---- -apiVersion: v1 -data: - cron: |+ - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 - -kind: ConfigMap -metadata: - name: cron-list - namespace: myproject-production ---- -apiVersion: v1 -data: - domains_urls.yaml: | - domains_urls: - - id: 1 - url: https://www.example.com - - id: 2 - url: https://www.example.sk -kind: ConfigMap -metadata: - name: domains-urls-m8t7497btf - namespace: myproject-production ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: cron - name: cron - namespace: myproject-production -spec: - progressDeadlineSeconds: 1500 - replicas: 1 - selector: - matchLabels: - app: cron - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - type: RollingUpdate - template: - metadata: - annotations: - logging/enabled: "true" - project/app: cron - project/environment: production - project/name: myproject - labels: - app: cron - date: "1234567890" - spec: - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: workload - operator: In - values: - - background - weight: 100 - containers: - - args: - - cd /var/www/html && ./phing warmup > /dev/null && rm -rf /tmp/log-pipe && - mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe && crontab -u root /var/spool/cron/template - && { crond || cron; } && stdbuf -o0 tail -n +1 -f /tmp/log-pipe - command: - - /bin/sh - - -c - env: - - name: ELASTICSEARCH_HOST - value: http://elasticsearch:9200 - - name: TRUSTED_PROXY - value: 10.0.0.0/8 - - name: DATABASE_NAME - value: myproject-production - - name: S3_ENDPOINT - value: https://s3.example.com - - name: MAILER_FORCE_WHITELIST - value: "false" - - name: DATABASE_USER - value: myproject-production - - name: DATABASE_PORT - value: "5432" - - name: MESSENGER_TRANSPORT_DSN - value: amqp://guest:guest@rabbitmq:5672/%2f/messages - - name: REDIS_PREFIX - value: myproject-production - - name: DATABASE_PASSWORD - value: test-db-password - - name: DATABASE_HOST - value: 10.0.0.100 - - name: ELASTIC_SEARCH_INDEX_PREFIX - value: myproject-production - - name: S3_SECRET - value: test-s3-secret - - name: MAILER_DSN - value: smtp://mailhog:1025 - - name: S3_BUCKET_NAME - value: myproject-production - - name: S3_ACCESS_KEY - value: myproject-production - - name: APP_SECRET - value: test-app-secret-key - image: v1.0.0 - imagePullPolicy: IfNotPresent - lifecycle: - preStop: - exec: - command: - - sleep - - "5" - name: cron - securityContext: - runAsUser: 0 - volumeMounts: - - mountPath: /var/www/html/config/domains_urls.yaml - name: domains-urls - subPath: domains_urls.yaml - - mountPath: /var/spool/cron/template - name: cron-list - subPath: cron - - mountPath: /root/.project_env.sh - name: cron-env - subPath: .project_env.sh - - mountPath: /var/www/html/config/frontend-api - name: fe-api-keys-volume - readOnly: true - workingDir: /var/www/html - imagePullSecrets: - - name: dockerregistry - tolerations: - - effect: NoSchedule - key: workload - operator: Equal - value: background - volumes: - - configMap: - name: domains-urls-m8t7497btf - name: domains-urls - - configMap: - name: cron-list - name: cron-list - - configMap: - name: cron-env - name: cron-env - - name: fe-api-keys-volume - secret: - defaultMode: 420 - secretName: fe-api-keys diff --git a/tests/scenarios/basic-production/expected/horizontalPodAutoscaler.yaml b/tests/scenarios/basic-production/expected/horizontalPodAutoscaler.yaml deleted file mode 100644 index 74fbf30..0000000 --- a/tests/scenarios/basic-production/expected/horizontalPodAutoscaler.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: webserver-php-fpm - namespace: "myproject-production" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: webserver-php-fpm - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: ContainerResource - containerResource: - name: cpu - container: php-fpm - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/basic-production/expected/horizontalStorefrontAutoscaler.yaml b/tests/scenarios/basic-production/expected/horizontalStorefrontAutoscaler.yaml deleted file mode 100644 index 212d868..0000000 --- a/tests/scenarios/basic-production/expected/horizontalStorefrontAutoscaler.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: storefront - namespace: "myproject-production" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: storefront - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/basic-production/expected/migrate-continuous-deploy.yaml b/tests/scenarios/basic-production/expected/migrate-continuous-deploy.yaml index 79076f9..9305d46 100644 --- a/tests/scenarios/basic-production/expected/migrate-continuous-deploy.yaml +++ b/tests/scenarios/basic-production/expected/migrate-continuous-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -236,19 +231,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -285,6 +267,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -330,22 +325,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/basic-production/expected/migrate-first-deploy-with-demo-data.yaml b/tests/scenarios/basic-production/expected/migrate-first-deploy-with-demo-data.yaml index bf040b1..678ed98 100644 --- a/tests/scenarios/basic-production/expected/migrate-first-deploy-with-demo-data.yaml +++ b/tests/scenarios/basic-production/expected/migrate-first-deploy-with-demo-data.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -236,19 +231,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -285,6 +267,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -330,22 +325,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/basic-production/expected/migrate-first-deploy.yaml b/tests/scenarios/basic-production/expected/migrate-first-deploy.yaml index 7b9ec6c..917eb46 100644 --- a/tests/scenarios/basic-production/expected/migrate-first-deploy.yaml +++ b/tests/scenarios/basic-production/expected/migrate-first-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -236,19 +231,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -285,6 +267,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -330,22 +325,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/basic-production/expected/namespace.yaml b/tests/scenarios/basic-production/expected/namespace.yaml deleted file mode 100644 index 47f129e..0000000 --- a/tests/scenarios/basic-production/expected/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "myproject-production" diff --git a/tests/scenarios/basic-production/expected/webserver.yaml b/tests/scenarios/basic-production/expected/webserver.yaml index 1b8af9e..e671161 100644 --- a/tests/scenarios/basic-production/expected/webserver.yaml +++ b/tests/scenarios/basic-production/expected/webserver.yaml @@ -1,7 +1,38 @@ apiVersion: v1 -kind: Namespace +data: + .project_env.sh: | + export ELASTICSEARCH_HOST='http://elasticsearch:9200' + export TRUSTED_PROXY='10.0.0.0/8' + export DATABASE_NAME='myproject-production' + export S3_ENDPOINT='https://s3.example.com' + export MAILER_FORCE_WHITELIST='false' + export DATABASE_USER='myproject-production' + export DATABASE_PORT='5432' + export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' + export REDIS_PREFIX='myproject-production' + export DATABASE_PASSWORD='test-db-password' + export DATABASE_HOST='10.0.0.100' + export ELASTIC_SEARCH_INDEX_PREFIX='myproject-production' + export S3_SECRET='test-s3-secret' + export MAILER_DSN='smtp://mailhog:1025' + export S3_BUCKET_NAME='myproject-production' + export S3_ACCESS_KEY='myproject-production' + export APP_SECRET='test-app-secret-key' +kind: ConfigMap metadata: - name: myproject-production + name: cron-env + namespace: myproject-production +--- +apiVersion: v1 +data: + cron: |+ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 + +kind: ConfigMap +metadata: + name: cron-list + namespace: myproject-production --- apiVersion: v1 data: @@ -88,8 +119,15 @@ data: root /var/www/html/web; location /health { - stub_status on; access_log off; + + include fastcgi_params; + fastcgi_read_timeout 3s; + fastcgi_param SCRIPT_FILENAME /ping; + fastcgi_param SCRIPT_NAME /ping; + fastcgi_param REQUEST_METHOD GET; + + fastcgi_pass php-upstream; } } @@ -317,6 +355,8 @@ data: [www] listen = 127.0.0.1:9000 + ping.path = /ping + ping.response = pong pm = dynamic pm.max_children = 20 @@ -379,6 +419,138 @@ spec: --- apiVersion: apps/v1 kind: Deployment +metadata: + labels: + app: cron + name: cron + namespace: myproject-production +spec: + replicas: 1 + selector: + matchLabels: + app: cron + strategy: + type: Recreate + template: + metadata: + annotations: + logging/enabled: "true" + project/app: cron + project/environment: production + project/name: myproject + labels: + app: cron + date: "1234567890" + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: workload + operator: In + values: + - background + weight: 100 + containers: + - args: + - | + ./phing warmup > /dev/null + # FIFO for logs rm -f /tmp/log-pipe && mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe + # crontab crontab -u root /var/spool/cron/template + # run on backround stdbuf -o0 tail -n +1 -f /tmp/log-pipe & + exec crond -f || exec cron -f + command: + - /bin/sh + - -lc + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: myproject-production + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "false" + - name: DATABASE_USER + value: myproject-production + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: myproject-production + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: myproject-production + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: myproject-production + - name: S3_ACCESS_KEY + value: myproject-production + - name: APP_SECRET + value: test-app-secret-key + image: v1.0.0 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -lc + - | + ( ./bin/console deploy:cron:lock > /tmp/cron-lock.log 2>&1 || true ) & + ./bin/console deploy:cron:watch || true + name: cron + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml + - mountPath: /var/spool/cron/template + name: cron-list + subPath: cron + - mountPath: /root/.project_env.sh + name: cron-env + subPath: .project_env.sh + - mountPath: /var/www/html/config/frontend-api + name: fe-api-keys-volume + readOnly: true + workingDir: /var/www/html + imagePullSecrets: + - name: dockerregistry + terminationGracePeriodSeconds: 3000 + tolerations: + - effect: NoSchedule + key: workload + operator: Equal + value: background + volumes: + - configMap: + name: domains-urls-m8t7497btf + name: domains-urls + - configMap: + name: cron-list + name: cron-list + - configMap: + name: cron-env + name: cron-env + - name: fe-api-keys-volume + secret: + defaultMode: 420 + secretName: fe-api-keys +--- +apiVersion: apps/v1 +kind: Deployment metadata: name: storefront namespace: myproject-production @@ -387,6 +559,11 @@ spec: selector: matchLabels: app: storefront + strategy: + rollingUpdate: + maxSurge: 50% + maxUnavailable: 0 + type: RollingUpdate template: metadata: annotations: @@ -426,33 +603,42 @@ spec: preStop: exec: command: - - sleep - - "10" + - /bin/sh + - -lc + - sleep 10 livenessProbe: + failureThreshold: 3 httpGet: path: /api/health port: 3000 - initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 2 name: storefront ports: - containerPort: 3000 name: storefront protocol: TCP readinessProbe: + failureThreshold: 1 httpGet: path: /api/health port: 3000 initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 3 + timeoutSeconds: 2 resources: limits: memory: 1.5Gi requests: cpu: 500m memory: 800Mi + startupProbe: + failureThreshold: 60 + httpGet: + path: /api/health + port: 3000 + periodSeconds: 2 + timeoutSeconds: 2 imagePullSecrets: - name: dockerregistry terminationGracePeriodSeconds: 60 @@ -472,7 +658,7 @@ spec: app: webserver-php-fpm strategy: rollingUpdate: - maxSurge: 1 + maxSurge: 50% maxUnavailable: 0 type: RollingUpdate template: @@ -547,19 +733,25 @@ spec: image: v1.0.0 imagePullPolicy: IfNotPresent lifecycle: - postStart: - exec: - command: - - /var/www/html/phing - - -S - - warmup preStop: exec: command: - - sh - - -c - - sleep 10 && kill -SIGQUIT 1 + - /bin/sh + - -lc + - sleep 10; kill -QUIT 1 || true + livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 10 + tcpSocket: + port: 9000 + timeoutSeconds: 2 name: php-fpm + readinessProbe: + initialDelaySeconds: 2 + periodSeconds: 5 + tcpSocket: + port: 9000 + timeoutSeconds: 2 resources: limits: memory: 2Gi @@ -591,23 +783,27 @@ spec: - -c - sleep 5 && /usr/sbin/nginx -s quit livenessProbe: + failureThreshold: 6 httpGet: path: /health - port: 80 + port: health initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 3 name: webserver ports: - containerPort: 8080 name: http + - containerPort: 80 + name: health readinessProbe: + failureThreshold: 3 httpGet: path: /health - port: 80 - initialDelaySeconds: 5 + port: health + initialDelaySeconds: 2 periodSeconds: 5 - timeoutSeconds: 5 + timeoutSeconds: 2 resources: limits: memory: 300Mi @@ -644,6 +840,53 @@ spec: - mountPath: /var/www/html/config/domains_urls.yaml name: domains-urls subPath: domains_urls.yaml + - command: + - /var/www/html/phing + - -S + - warmup + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: myproject-production + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "false" + - name: DATABASE_USER + value: myproject-production + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: myproject-production + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: myproject-production + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: myproject-production + - name: S3_ACCESS_KEY + value: myproject-production + - name: APP_SECRET + value: test-app-secret-key + image: v1.0.0 + name: warmup + volumeMounts: + - mountPath: /var/www/html + name: source-codes + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml terminationGracePeriodSeconds: 120 volumes: - emptyDir: {} @@ -665,6 +908,89 @@ spec: defaultMode: 420 secretName: fe-api-keys --- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: storefront + namespace: myproject-production +spec: + behavior: + scaleDown: + policies: + - periodSeconds: 60 + type: Pods + value: 1 + - periodSeconds: 60 + type: Percent + value: 30 + selectPolicy: Max + stabilizationWindowSeconds: 600 + scaleUp: + policies: + - periodSeconds: 60 + type: Pods + value: 2 + - periodSeconds: 60 + type: Percent + value: 50 + selectPolicy: Max + stabilizationWindowSeconds: 60 + maxReplicas: 3 + metrics: + - resource: + name: cpu + target: + averageUtilization: 120 + type: Utilization + type: Resource + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: storefront +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: webserver-php-fpm + namespace: myproject-production +spec: + behavior: + scaleDown: + policies: + - periodSeconds: 60 + type: Pods + value: 1 + - periodSeconds: 60 + type: Percent + value: 30 + selectPolicy: Max + stabilizationWindowSeconds: 600 + scaleUp: + policies: + - periodSeconds: 60 + type: Pods + value: 2 + - periodSeconds: 60 + type: Percent + value: 50 + selectPolicy: Max + stabilizationWindowSeconds: 60 + maxReplicas: 3 + metrics: + - containerResource: + container: php-fpm + name: cpu + target: + averageUtilization: 120 + type: Utilization + type: ContainerResource + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: webserver-php-fpm +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: diff --git a/tests/scenarios/development-single-domain/deploy-project.sh b/tests/scenarios/development-single-domain/deploy-project.sh index 4858fbe..46eca63 100644 --- a/tests/scenarios/development-single-domain/deploy-project.sh +++ b/tests/scenarios/development-single-domain/deploy-project.sh @@ -6,7 +6,7 @@ source "$(dirname "$0")/../../lib/scenario-base.sh" DOMAINS=(DOMAIN_HOSTNAME_1) export RUNNING_PRODUCTION=0 export WHITELIST_IPS="10.0.0.0/8,192.168.0.0/16" -ENABLE_AUTOSCALING=true +ENABLE_AUTOSCALING=false declare -A CRON_INSTANCES=( ["cron"]='*/5 * * * *' diff --git a/tests/scenarios/development-single-domain/expected/cron.yaml b/tests/scenarios/development-single-domain/expected/cron.yaml deleted file mode 100644 index faae19b..0000000 --- a/tests/scenarios/development-single-domain/expected/cron.yaml +++ /dev/null @@ -1,180 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: myproject-dev ---- -apiVersion: v1 -data: - .project_env.sh: | - export ELASTICSEARCH_HOST='http://elasticsearch:9200' - export TRUSTED_PROXY='10.0.0.0/8' - export DATABASE_NAME='myproject-dev' - export S3_ENDPOINT='https://s3.example.com' - export MAILER_FORCE_WHITELIST='true' - export DATABASE_USER='myproject-dev' - export DATABASE_PORT='5432' - export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' - export REDIS_PREFIX='myproject-dev' - export DATABASE_PASSWORD='test-db-password' - export DATABASE_HOST='10.0.0.100' - export ELASTIC_SEARCH_INDEX_PREFIX='myproject-dev' - export S3_SECRET='test-s3-secret' - export MAILER_DSN='smtp://mailhog:1025' - export S3_BUCKET_NAME='myproject-dev' - export S3_ACCESS_KEY='myproject-dev' - export APP_SECRET='test-app-secret-key' -kind: ConfigMap -metadata: - name: cron-env - namespace: myproject-dev ---- -apiVersion: v1 -data: - cron: |+ - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 - -kind: ConfigMap -metadata: - name: cron-list - namespace: myproject-dev ---- -apiVersion: v1 -data: - domains_urls.yaml: | - domains_urls: - - id: 1 - url: https://dev.example.com -kind: ConfigMap -metadata: - name: domains-urls-5f46tgkghd - namespace: myproject-dev ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: cron - name: cron - namespace: myproject-dev -spec: - progressDeadlineSeconds: 1500 - replicas: 1 - selector: - matchLabels: - app: cron - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - type: RollingUpdate - template: - metadata: - annotations: - logging/enabled: "true" - project/app: cron - project/environment: dev - project/name: myproject - labels: - app: cron - date: "1234567890" - spec: - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: workload - operator: In - values: - - background - weight: 100 - containers: - - args: - - cd /var/www/html && ./phing warmup > /dev/null && rm -rf /tmp/log-pipe && - mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe && crontab -u root /var/spool/cron/template - && { crond || cron; } && stdbuf -o0 tail -n +1 -f /tmp/log-pipe - command: - - /bin/sh - - -c - env: - - name: ELASTICSEARCH_HOST - value: http://elasticsearch:9200 - - name: TRUSTED_PROXY - value: 10.0.0.0/8 - - name: DATABASE_NAME - value: myproject-dev - - name: S3_ENDPOINT - value: https://s3.example.com - - name: MAILER_FORCE_WHITELIST - value: "true" - - name: DATABASE_USER - value: myproject-dev - - name: DATABASE_PORT - value: "5432" - - name: MESSENGER_TRANSPORT_DSN - value: amqp://guest:guest@rabbitmq:5672/%2f/messages - - name: REDIS_PREFIX - value: myproject-dev - - name: DATABASE_PASSWORD - value: test-db-password - - name: DATABASE_HOST - value: 10.0.0.100 - - name: ELASTIC_SEARCH_INDEX_PREFIX - value: myproject-dev - - name: S3_SECRET - value: test-s3-secret - - name: MAILER_DSN - value: smtp://mailhog:1025 - - name: S3_BUCKET_NAME - value: myproject-dev - - name: S3_ACCESS_KEY - value: myproject-dev - - name: APP_SECRET - value: test-app-secret-key - image: dev-latest - imagePullPolicy: IfNotPresent - lifecycle: - preStop: - exec: - command: - - sleep - - "5" - name: cron - securityContext: - runAsUser: 0 - volumeMounts: - - mountPath: /var/www/html/config/domains_urls.yaml - name: domains-urls - subPath: domains_urls.yaml - - mountPath: /var/spool/cron/template - name: cron-list - subPath: cron - - mountPath: /root/.project_env.sh - name: cron-env - subPath: .project_env.sh - - mountPath: /var/www/html/config/frontend-api - name: fe-api-keys-volume - readOnly: true - workingDir: /var/www/html - imagePullSecrets: - - name: dockerregistry - tolerations: - - effect: NoSchedule - key: workload - operator: Equal - value: background - volumes: - - configMap: - name: domains-urls-5f46tgkghd - name: domains-urls - - configMap: - name: cron-list - name: cron-list - - configMap: - name: cron-env - name: cron-env - - name: fe-api-keys-volume - secret: - defaultMode: 420 - secretName: fe-api-keys diff --git a/tests/scenarios/development-single-domain/expected/horizontalPodAutoscaler.yaml b/tests/scenarios/development-single-domain/expected/horizontalPodAutoscaler.yaml deleted file mode 100644 index 95e34f3..0000000 --- a/tests/scenarios/development-single-domain/expected/horizontalPodAutoscaler.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: webserver-php-fpm - namespace: "myproject-dev" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: webserver-php-fpm - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: ContainerResource - containerResource: - name: cpu - container: php-fpm - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/development-single-domain/expected/horizontalStorefrontAutoscaler.yaml b/tests/scenarios/development-single-domain/expected/horizontalStorefrontAutoscaler.yaml deleted file mode 100644 index 892de0a..0000000 --- a/tests/scenarios/development-single-domain/expected/horizontalStorefrontAutoscaler.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: storefront - namespace: "myproject-dev" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: storefront - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/development-single-domain/expected/migrate-continuous-deploy.yaml b/tests/scenarios/development-single-domain/expected/migrate-continuous-deploy.yaml index 0e74d2e..b5ba1ae 100644 --- a/tests/scenarios/development-single-domain/expected/migrate-continuous-deploy.yaml +++ b/tests/scenarios/development-single-domain/expected/migrate-continuous-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-dev ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -117,19 +112,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -166,6 +148,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -211,22 +206,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/development-single-domain/expected/migrate-first-deploy-with-demo-data.yaml b/tests/scenarios/development-single-domain/expected/migrate-first-deploy-with-demo-data.yaml index 76dc46e..9de21ed 100644 --- a/tests/scenarios/development-single-domain/expected/migrate-first-deploy-with-demo-data.yaml +++ b/tests/scenarios/development-single-domain/expected/migrate-first-deploy-with-demo-data.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-dev ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -117,19 +112,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -166,6 +148,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -211,22 +206,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/development-single-domain/expected/migrate-first-deploy.yaml b/tests/scenarios/development-single-domain/expected/migrate-first-deploy.yaml index a047f20..a4284c3 100644 --- a/tests/scenarios/development-single-domain/expected/migrate-first-deploy.yaml +++ b/tests/scenarios/development-single-domain/expected/migrate-first-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-dev ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -117,19 +112,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -166,6 +148,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -211,22 +206,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/development-single-domain/expected/namespace.yaml b/tests/scenarios/development-single-domain/expected/namespace.yaml deleted file mode 100644 index 9827882..0000000 --- a/tests/scenarios/development-single-domain/expected/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "myproject-dev" diff --git a/tests/scenarios/development-single-domain/expected/webserver.yaml b/tests/scenarios/development-single-domain/expected/webserver.yaml index f2dd9ea..88032a0 100644 --- a/tests/scenarios/development-single-domain/expected/webserver.yaml +++ b/tests/scenarios/development-single-domain/expected/webserver.yaml @@ -1,7 +1,38 @@ apiVersion: v1 -kind: Namespace +data: + .project_env.sh: | + export ELASTICSEARCH_HOST='http://elasticsearch:9200' + export TRUSTED_PROXY='10.0.0.0/8' + export DATABASE_NAME='myproject-dev' + export S3_ENDPOINT='https://s3.example.com' + export MAILER_FORCE_WHITELIST='true' + export DATABASE_USER='myproject-dev' + export DATABASE_PORT='5432' + export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' + export REDIS_PREFIX='myproject-dev' + export DATABASE_PASSWORD='test-db-password' + export DATABASE_HOST='10.0.0.100' + export ELASTIC_SEARCH_INDEX_PREFIX='myproject-dev' + export S3_SECRET='test-s3-secret' + export MAILER_DSN='smtp://mailhog:1025' + export S3_BUCKET_NAME='myproject-dev' + export S3_ACCESS_KEY='myproject-dev' + export APP_SECRET='test-app-secret-key' +kind: ConfigMap +metadata: + name: cron-env + namespace: myproject-dev +--- +apiVersion: v1 +data: + cron: |+ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 + +kind: ConfigMap metadata: - name: myproject-dev + name: cron-list + namespace: myproject-dev --- apiVersion: v1 data: @@ -86,8 +117,15 @@ data: root /var/www/html/web; location /health { - stub_status on; access_log off; + + include fastcgi_params; + fastcgi_read_timeout 3s; + fastcgi_param SCRIPT_FILENAME /ping; + fastcgi_param SCRIPT_NAME /ping; + fastcgi_param REQUEST_METHOD GET; + + fastcgi_pass php-upstream; } } @@ -315,6 +353,8 @@ data: [www] listen = 127.0.0.1:9000 + ping.path = /ping + ping.response = pong pm = dynamic pm.max_children = 20 @@ -377,6 +417,138 @@ spec: --- apiVersion: apps/v1 kind: Deployment +metadata: + labels: + app: cron + name: cron + namespace: myproject-dev +spec: + replicas: 1 + selector: + matchLabels: + app: cron + strategy: + type: Recreate + template: + metadata: + annotations: + logging/enabled: "true" + project/app: cron + project/environment: dev + project/name: myproject + labels: + app: cron + date: "1234567890" + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: workload + operator: In + values: + - background + weight: 100 + containers: + - args: + - | + ./phing warmup > /dev/null + # FIFO for logs rm -f /tmp/log-pipe && mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe + # crontab crontab -u root /var/spool/cron/template + # run on backround stdbuf -o0 tail -n +1 -f /tmp/log-pipe & + exec crond -f || exec cron -f + command: + - /bin/sh + - -lc + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: myproject-dev + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "true" + - name: DATABASE_USER + value: myproject-dev + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: myproject-dev + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: myproject-dev + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: myproject-dev + - name: S3_ACCESS_KEY + value: myproject-dev + - name: APP_SECRET + value: test-app-secret-key + image: dev-latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -lc + - | + ( ./bin/console deploy:cron:lock > /tmp/cron-lock.log 2>&1 || true ) & + ./bin/console deploy:cron:watch || true + name: cron + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml + - mountPath: /var/spool/cron/template + name: cron-list + subPath: cron + - mountPath: /root/.project_env.sh + name: cron-env + subPath: .project_env.sh + - mountPath: /var/www/html/config/frontend-api + name: fe-api-keys-volume + readOnly: true + workingDir: /var/www/html + imagePullSecrets: + - name: dockerregistry + terminationGracePeriodSeconds: 3000 + tolerations: + - effect: NoSchedule + key: workload + operator: Equal + value: background + volumes: + - configMap: + name: domains-urls-5f46tgkghd + name: domains-urls + - configMap: + name: cron-list + name: cron-list + - configMap: + name: cron-env + name: cron-env + - name: fe-api-keys-volume + secret: + defaultMode: 420 + secretName: fe-api-keys +--- +apiVersion: apps/v1 +kind: Deployment metadata: name: storefront namespace: myproject-dev @@ -385,6 +557,11 @@ spec: selector: matchLabels: app: storefront + strategy: + rollingUpdate: + maxSurge: 50% + maxUnavailable: 0 + type: RollingUpdate template: metadata: annotations: @@ -420,33 +597,42 @@ spec: preStop: exec: command: - - sleep - - "10" + - /bin/sh + - -lc + - sleep 10 livenessProbe: + failureThreshold: 3 httpGet: path: /api/health port: 3000 - initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 2 name: storefront ports: - containerPort: 3000 name: storefront protocol: TCP readinessProbe: + failureThreshold: 1 httpGet: path: /api/health port: 3000 initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 3 + timeoutSeconds: 2 resources: limits: memory: 1.5Gi requests: cpu: 500m memory: 800Mi + startupProbe: + failureThreshold: 60 + httpGet: + path: /api/health + port: 3000 + periodSeconds: 2 + timeoutSeconds: 2 imagePullSecrets: - name: dockerregistry terminationGracePeriodSeconds: 60 @@ -466,7 +652,7 @@ spec: app: webserver-php-fpm strategy: rollingUpdate: - maxSurge: 1 + maxSurge: 50% maxUnavailable: 0 type: RollingUpdate template: @@ -541,19 +727,25 @@ spec: image: dev-latest imagePullPolicy: IfNotPresent lifecycle: - postStart: - exec: - command: - - /var/www/html/phing - - -S - - warmup preStop: exec: command: - - sh - - -c - - sleep 10 && kill -SIGQUIT 1 + - /bin/sh + - -lc + - sleep 10; kill -QUIT 1 || true + livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 10 + tcpSocket: + port: 9000 + timeoutSeconds: 2 name: php-fpm + readinessProbe: + initialDelaySeconds: 2 + periodSeconds: 5 + tcpSocket: + port: 9000 + timeoutSeconds: 2 resources: limits: memory: 2Gi @@ -585,23 +777,27 @@ spec: - -c - sleep 5 && /usr/sbin/nginx -s quit livenessProbe: + failureThreshold: 6 httpGet: path: /health - port: 80 + port: health initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 3 name: webserver ports: - containerPort: 8080 name: http + - containerPort: 80 + name: health readinessProbe: + failureThreshold: 3 httpGet: path: /health - port: 80 - initialDelaySeconds: 5 + port: health + initialDelaySeconds: 2 periodSeconds: 5 - timeoutSeconds: 5 + timeoutSeconds: 2 resources: limits: memory: 300Mi @@ -638,6 +834,53 @@ spec: - mountPath: /var/www/html/config/domains_urls.yaml name: domains-urls subPath: domains_urls.yaml + - command: + - /var/www/html/phing + - -S + - warmup + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: myproject-dev + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "true" + - name: DATABASE_USER + value: myproject-dev + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: myproject-dev + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: myproject-dev + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: myproject-dev + - name: S3_ACCESS_KEY + value: myproject-dev + - name: APP_SECRET + value: test-app-secret-key + image: dev-latest + name: warmup + volumeMounts: + - mountPath: /var/www/html + name: source-codes + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml terminationGracePeriodSeconds: 120 volumes: - emptyDir: {} diff --git a/tests/scenarios/escaping-env/deploy-project.sh b/tests/scenarios/escaping-env/deploy-project.sh index 7911499..9d451c1 100644 --- a/tests/scenarios/escaping-env/deploy-project.sh +++ b/tests/scenarios/escaping-env/deploy-project.sh @@ -5,7 +5,6 @@ source "$(dirname "$0")/../../lib/scenario-base.sh" DOMAINS=(DOMAIN_HOSTNAME_1 DOMAIN_HOSTNAME_2) export RUNNING_PRODUCTION=1 export FIRST_DEPLOY=0 -ENABLE_AUTOSCALING=true declare -A CRON_INSTANCES=( ["cron"]='*/5 * * * *' diff --git a/tests/scenarios/escaping-env/expected/cron.yaml b/tests/scenarios/escaping-env/expected/cron.yaml deleted file mode 100644 index 759d1b1..0000000 --- a/tests/scenarios/escaping-env/expected/cron.yaml +++ /dev/null @@ -1,185 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 -data: - .project_env.sh: | - export ELASTICSEARCH_HOST='http://elasticsearch:9200' - export TRUSTED_PROXY='10.0.0.0/8' - export DATABASE_NAME='myproject-production' - export S3_ENDPOINT='https://s3.example.com' - export MAILER_FORCE_WHITELIST='false' - export DATABASE_USER='myproject-production' - export DATABASE_PORT='5432' - export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' - export REDIS_PREFIX='myproject-production' - export DATABASE_PASSWORD='test-db-password' - export DATABASE_HOST='10.0.0.100' - export ELASTIC_SEARCH_INDEX_PREFIX='myproject-production' - export SENTRY_RELEASE='479411e7' - export S3_SECRET='test-s3-secret' - export MAILER_DSN='smtp://mailhog:1025' - export S3_BUCKET_NAME='myproject-production' - export S3_ACCESS_KEY='myproject-production' - export APP_SECRET='test-app-secret-key' -kind: ConfigMap -metadata: - name: cron-env - namespace: myproject-production ---- -apiVersion: v1 -data: - cron: |+ - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 - -kind: ConfigMap -metadata: - name: cron-list - namespace: myproject-production ---- -apiVersion: v1 -data: - domains_urls.yaml: | - domains_urls: - - id: 1 - url: https://www.example.com - - id: 2 - url: https://www.example.sk -kind: ConfigMap -metadata: - name: domains-urls-m8t7497btf - namespace: myproject-production ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: cron - name: cron - namespace: myproject-production -spec: - progressDeadlineSeconds: 1500 - replicas: 1 - selector: - matchLabels: - app: cron - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - type: RollingUpdate - template: - metadata: - annotations: - logging/enabled: "true" - project/app: cron - project/environment: production - project/name: myproject - labels: - app: cron - date: "1234567890" - spec: - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: workload - operator: In - values: - - background - weight: 100 - containers: - - args: - - cd /var/www/html && ./phing warmup > /dev/null && rm -rf /tmp/log-pipe && - mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe && crontab -u root /var/spool/cron/template - && { crond || cron; } && stdbuf -o0 tail -n +1 -f /tmp/log-pipe - command: - - /bin/sh - - -c - env: - - name: ELASTICSEARCH_HOST - value: http://elasticsearch:9200 - - name: TRUSTED_PROXY - value: 10.0.0.0/8 - - name: DATABASE_NAME - value: myproject-production - - name: S3_ENDPOINT - value: https://s3.example.com - - name: MAILER_FORCE_WHITELIST - value: "false" - - name: DATABASE_USER - value: myproject-production - - name: DATABASE_PORT - value: "5432" - - name: MESSENGER_TRANSPORT_DSN - value: amqp://guest:guest@rabbitmq:5672/%2f/messages - - name: REDIS_PREFIX - value: myproject-production - - name: DATABASE_PASSWORD - value: test-db-password - - name: DATABASE_HOST - value: 10.0.0.100 - - name: ELASTIC_SEARCH_INDEX_PREFIX - value: myproject-production - - name: SENTRY_RELEASE - value: "479411e7" - - name: S3_SECRET - value: test-s3-secret - - name: MAILER_DSN - value: smtp://mailhog:1025 - - name: S3_BUCKET_NAME - value: myproject-production - - name: S3_ACCESS_KEY - value: myproject-production - - name: APP_SECRET - value: test-app-secret-key - image: v1.0.0 - imagePullPolicy: IfNotPresent - lifecycle: - preStop: - exec: - command: - - sleep - - "5" - name: cron - securityContext: - runAsUser: 0 - volumeMounts: - - mountPath: /var/www/html/config/domains_urls.yaml - name: domains-urls - subPath: domains_urls.yaml - - mountPath: /var/spool/cron/template - name: cron-list - subPath: cron - - mountPath: /root/.project_env.sh - name: cron-env - subPath: .project_env.sh - - mountPath: /var/www/html/config/frontend-api - name: fe-api-keys-volume - readOnly: true - workingDir: /var/www/html - imagePullSecrets: - - name: dockerregistry - tolerations: - - effect: NoSchedule - key: workload - operator: Equal - value: background - volumes: - - configMap: - name: domains-urls-m8t7497btf - name: domains-urls - - configMap: - name: cron-list - name: cron-list - - configMap: - name: cron-env - name: cron-env - - name: fe-api-keys-volume - secret: - defaultMode: 420 - secretName: fe-api-keys diff --git a/tests/scenarios/escaping-env/expected/horizontalPodAutoscaler.yaml b/tests/scenarios/escaping-env/expected/horizontalPodAutoscaler.yaml deleted file mode 100644 index 74fbf30..0000000 --- a/tests/scenarios/escaping-env/expected/horizontalPodAutoscaler.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: webserver-php-fpm - namespace: "myproject-production" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: webserver-php-fpm - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: ContainerResource - containerResource: - name: cpu - container: php-fpm - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/escaping-env/expected/horizontalStorefrontAutoscaler.yaml b/tests/scenarios/escaping-env/expected/horizontalStorefrontAutoscaler.yaml deleted file mode 100644 index 212d868..0000000 --- a/tests/scenarios/escaping-env/expected/horizontalStorefrontAutoscaler.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: storefront - namespace: "myproject-production" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: storefront - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/escaping-env/expected/migrate-continuous-deploy.yaml b/tests/scenarios/escaping-env/expected/migrate-continuous-deploy.yaml index 340088c..b3080de 100644 --- a/tests/scenarios/escaping-env/expected/migrate-continuous-deploy.yaml +++ b/tests/scenarios/escaping-env/expected/migrate-continuous-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -238,19 +233,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -287,6 +269,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -332,22 +327,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/escaping-env/expected/migrate-first-deploy-with-demo-data.yaml b/tests/scenarios/escaping-env/expected/migrate-first-deploy-with-demo-data.yaml index b81c351..1653b97 100644 --- a/tests/scenarios/escaping-env/expected/migrate-first-deploy-with-demo-data.yaml +++ b/tests/scenarios/escaping-env/expected/migrate-first-deploy-with-demo-data.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -238,19 +233,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -287,6 +269,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -332,22 +327,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/escaping-env/expected/migrate-first-deploy.yaml b/tests/scenarios/escaping-env/expected/migrate-first-deploy.yaml index 62b915e..74231ec 100644 --- a/tests/scenarios/escaping-env/expected/migrate-first-deploy.yaml +++ b/tests/scenarios/escaping-env/expected/migrate-first-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: myproject-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -238,19 +233,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -287,6 +269,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -332,22 +327,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/escaping-env/expected/namespace.yaml b/tests/scenarios/escaping-env/expected/namespace.yaml deleted file mode 100644 index 47f129e..0000000 --- a/tests/scenarios/escaping-env/expected/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "myproject-production" diff --git a/tests/scenarios/escaping-env/expected/webserver.yaml b/tests/scenarios/escaping-env/expected/webserver.yaml index dc64a13..1d92237 100644 --- a/tests/scenarios/escaping-env/expected/webserver.yaml +++ b/tests/scenarios/escaping-env/expected/webserver.yaml @@ -1,7 +1,39 @@ apiVersion: v1 -kind: Namespace +data: + .project_env.sh: | + export ELASTICSEARCH_HOST='http://elasticsearch:9200' + export TRUSTED_PROXY='10.0.0.0/8' + export DATABASE_NAME='myproject-production' + export S3_ENDPOINT='https://s3.example.com' + export MAILER_FORCE_WHITELIST='false' + export DATABASE_USER='myproject-production' + export DATABASE_PORT='5432' + export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' + export REDIS_PREFIX='myproject-production' + export DATABASE_PASSWORD='test-db-password' + export DATABASE_HOST='10.0.0.100' + export ELASTIC_SEARCH_INDEX_PREFIX='myproject-production' + export SENTRY_RELEASE='479411e7' + export S3_SECRET='test-s3-secret' + export MAILER_DSN='smtp://mailhog:1025' + export S3_BUCKET_NAME='myproject-production' + export S3_ACCESS_KEY='myproject-production' + export APP_SECRET='test-app-secret-key' +kind: ConfigMap metadata: - name: myproject-production + name: cron-env + namespace: myproject-production +--- +apiVersion: v1 +data: + cron: |+ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 + +kind: ConfigMap +metadata: + name: cron-list + namespace: myproject-production --- apiVersion: v1 data: @@ -88,8 +120,15 @@ data: root /var/www/html/web; location /health { - stub_status on; access_log off; + + include fastcgi_params; + fastcgi_read_timeout 3s; + fastcgi_param SCRIPT_FILENAME /ping; + fastcgi_param SCRIPT_NAME /ping; + fastcgi_param REQUEST_METHOD GET; + + fastcgi_pass php-upstream; } } @@ -317,6 +356,8 @@ data: [www] listen = 127.0.0.1:9000 + ping.path = /ping + ping.response = pong pm = dynamic pm.max_children = 20 @@ -379,6 +420,140 @@ spec: --- apiVersion: apps/v1 kind: Deployment +metadata: + labels: + app: cron + name: cron + namespace: myproject-production +spec: + replicas: 1 + selector: + matchLabels: + app: cron + strategy: + type: Recreate + template: + metadata: + annotations: + logging/enabled: "true" + project/app: cron + project/environment: production + project/name: myproject + labels: + app: cron + date: "1234567890" + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: workload + operator: In + values: + - background + weight: 100 + containers: + - args: + - | + ./phing warmup > /dev/null + # FIFO for logs rm -f /tmp/log-pipe && mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe + # crontab crontab -u root /var/spool/cron/template + # run on backround stdbuf -o0 tail -n +1 -f /tmp/log-pipe & + exec crond -f || exec cron -f + command: + - /bin/sh + - -lc + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: myproject-production + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "false" + - name: DATABASE_USER + value: myproject-production + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: myproject-production + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: myproject-production + - name: SENTRY_RELEASE + value: "479411e7" + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: myproject-production + - name: S3_ACCESS_KEY + value: myproject-production + - name: APP_SECRET + value: test-app-secret-key + image: v1.0.0 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -lc + - | + ( ./bin/console deploy:cron:lock > /tmp/cron-lock.log 2>&1 || true ) & + ./bin/console deploy:cron:watch || true + name: cron + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml + - mountPath: /var/spool/cron/template + name: cron-list + subPath: cron + - mountPath: /root/.project_env.sh + name: cron-env + subPath: .project_env.sh + - mountPath: /var/www/html/config/frontend-api + name: fe-api-keys-volume + readOnly: true + workingDir: /var/www/html + imagePullSecrets: + - name: dockerregistry + terminationGracePeriodSeconds: 3000 + tolerations: + - effect: NoSchedule + key: workload + operator: Equal + value: background + volumes: + - configMap: + name: domains-urls-m8t7497btf + name: domains-urls + - configMap: + name: cron-list + name: cron-list + - configMap: + name: cron-env + name: cron-env + - name: fe-api-keys-volume + secret: + defaultMode: 420 + secretName: fe-api-keys +--- +apiVersion: apps/v1 +kind: Deployment metadata: name: storefront namespace: myproject-production @@ -387,6 +562,11 @@ spec: selector: matchLabels: app: storefront + strategy: + rollingUpdate: + maxSurge: 50% + maxUnavailable: 0 + type: RollingUpdate template: metadata: annotations: @@ -428,33 +608,42 @@ spec: preStop: exec: command: - - sleep - - "10" + - /bin/sh + - -lc + - sleep 10 livenessProbe: + failureThreshold: 3 httpGet: path: /api/health port: 3000 - initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 2 name: storefront ports: - containerPort: 3000 name: storefront protocol: TCP readinessProbe: + failureThreshold: 1 httpGet: path: /api/health port: 3000 initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 3 + timeoutSeconds: 2 resources: limits: memory: 1.5Gi requests: cpu: 500m memory: 800Mi + startupProbe: + failureThreshold: 60 + httpGet: + path: /api/health + port: 3000 + periodSeconds: 2 + timeoutSeconds: 2 imagePullSecrets: - name: dockerregistry terminationGracePeriodSeconds: 60 @@ -474,7 +663,7 @@ spec: app: webserver-php-fpm strategy: rollingUpdate: - maxSurge: 1 + maxSurge: 50% maxUnavailable: 0 type: RollingUpdate template: @@ -551,19 +740,25 @@ spec: image: v1.0.0 imagePullPolicy: IfNotPresent lifecycle: - postStart: - exec: - command: - - /var/www/html/phing - - -S - - warmup preStop: exec: command: - - sh - - -c - - sleep 10 && kill -SIGQUIT 1 + - /bin/sh + - -lc + - sleep 10; kill -QUIT 1 || true + livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 10 + tcpSocket: + port: 9000 + timeoutSeconds: 2 name: php-fpm + readinessProbe: + initialDelaySeconds: 2 + periodSeconds: 5 + tcpSocket: + port: 9000 + timeoutSeconds: 2 resources: limits: memory: 2Gi @@ -595,23 +790,27 @@ spec: - -c - sleep 5 && /usr/sbin/nginx -s quit livenessProbe: + failureThreshold: 6 httpGet: path: /health - port: 80 + port: health initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 3 name: webserver ports: - containerPort: 8080 name: http + - containerPort: 80 + name: health readinessProbe: + failureThreshold: 3 httpGet: path: /health - port: 80 - initialDelaySeconds: 5 + port: health + initialDelaySeconds: 2 periodSeconds: 5 - timeoutSeconds: 5 + timeoutSeconds: 2 resources: limits: memory: 300Mi @@ -648,6 +847,55 @@ spec: - mountPath: /var/www/html/config/domains_urls.yaml name: domains-urls subPath: domains_urls.yaml + - command: + - /var/www/html/phing + - -S + - warmup + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: myproject-production + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "false" + - name: DATABASE_USER + value: myproject-production + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: myproject-production + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: myproject-production + - name: SENTRY_RELEASE + value: "479411e7" + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: myproject-production + - name: S3_ACCESS_KEY + value: myproject-production + - name: APP_SECRET + value: test-app-secret-key + image: v1.0.0 + name: warmup + volumeMounts: + - mountPath: /var/www/html + name: source-codes + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml terminationGracePeriodSeconds: 120 volumes: - emptyDir: {} @@ -669,6 +917,89 @@ spec: defaultMode: 420 secretName: fe-api-keys --- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: storefront + namespace: myproject-production +spec: + behavior: + scaleDown: + policies: + - periodSeconds: 60 + type: Pods + value: 1 + - periodSeconds: 60 + type: Percent + value: 30 + selectPolicy: Max + stabilizationWindowSeconds: 600 + scaleUp: + policies: + - periodSeconds: 60 + type: Pods + value: 2 + - periodSeconds: 60 + type: Percent + value: 50 + selectPolicy: Max + stabilizationWindowSeconds: 60 + maxReplicas: 3 + metrics: + - resource: + name: cpu + target: + averageUtilization: 120 + type: Utilization + type: Resource + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: storefront +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: webserver-php-fpm + namespace: myproject-production +spec: + behavior: + scaleDown: + policies: + - periodSeconds: 60 + type: Pods + value: 1 + - periodSeconds: 60 + type: Percent + value: 30 + selectPolicy: Max + stabilizationWindowSeconds: 600 + scaleUp: + policies: + - periodSeconds: 60 + type: Pods + value: 2 + - periodSeconds: 60 + type: Percent + value: 50 + selectPolicy: Max + stabilizationWindowSeconds: 60 + maxReplicas: 3 + metrics: + - containerResource: + container: php-fpm + name: cpu + target: + averageUtilization: 120 + type: Utilization + type: ContainerResource + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: webserver-php-fpm +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: diff --git a/tests/scenarios/production-with-cloudflare/deploy-project.sh b/tests/scenarios/production-with-cloudflare/deploy-project.sh index dbcece0..71a5250 100644 --- a/tests/scenarios/production-with-cloudflare/deploy-project.sh +++ b/tests/scenarios/production-with-cloudflare/deploy-project.sh @@ -7,7 +7,6 @@ DOMAINS=(DOMAIN_HOSTNAME_1 DOMAIN_HOSTNAME_2) export RUNNING_PRODUCTION=1 export USING_CLOUDFLARE=1 export CLOUDFLARE_IPS="103.21.244.0/22,103.22.200.0/22,104.16.0.0/13" -ENABLE_AUTOSCALING=true declare -A CRON_INSTANCES=( ["cron"]='*/5 * * * *' diff --git a/tests/scenarios/production-with-cloudflare/expected/cron.yaml b/tests/scenarios/production-with-cloudflare/expected/cron.yaml deleted file mode 100644 index 4604bb6..0000000 --- a/tests/scenarios/production-with-cloudflare/expected/cron.yaml +++ /dev/null @@ -1,183 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: shop-production ---- -apiVersion: v1 -data: - .project_env.sh: | - export ELASTICSEARCH_HOST='http://elasticsearch:9200' - export TRUSTED_PROXY='10.0.0.0/8' - export DATABASE_NAME='shop-production' - export S3_ENDPOINT='https://s3.example.com' - export MAILER_FORCE_WHITELIST='false' - export DATABASE_USER='shop-production' - export DATABASE_PORT='5432' - export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' - export REDIS_PREFIX='shop-production' - export DATABASE_PASSWORD='test-db-password' - export DATABASE_HOST='10.0.0.100' - export ELASTIC_SEARCH_INDEX_PREFIX='shop-production' - export S3_SECRET='test-s3-secret' - export MAILER_DSN='smtp://mailhog:1025' - export S3_BUCKET_NAME='shop-production' - export S3_ACCESS_KEY='shop-production' - export APP_SECRET='test-app-secret-key' -kind: ConfigMap -metadata: - name: cron-env - namespace: shop-production ---- -apiVersion: v1 -data: - cron: |+ - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 - 0 */2 * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing feed-generator > /dev/null 2>&1 - -kind: ConfigMap -metadata: - name: cron-list - namespace: shop-production ---- -apiVersion: v1 -data: - domains_urls.yaml: | - domains_urls: - - id: 1 - url: https://www.shop.com - - id: 2 - url: https://www.shop.de -kind: ConfigMap -metadata: - name: domains-urls-47t6ghttc4 - namespace: shop-production ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: cron - name: cron - namespace: shop-production -spec: - progressDeadlineSeconds: 1500 - replicas: 1 - selector: - matchLabels: - app: cron - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - type: RollingUpdate - template: - metadata: - annotations: - logging/enabled: "true" - project/app: cron - project/environment: production - project/name: shop - labels: - app: cron - date: "1234567890" - spec: - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: workload - operator: In - values: - - background - weight: 100 - containers: - - args: - - cd /var/www/html && ./phing warmup > /dev/null && rm -rf /tmp/log-pipe && - mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe && crontab -u root /var/spool/cron/template - && { crond || cron; } && stdbuf -o0 tail -n +1 -f /tmp/log-pipe - command: - - /bin/sh - - -c - env: - - name: ELASTICSEARCH_HOST - value: http://elasticsearch:9200 - - name: TRUSTED_PROXY - value: 10.0.0.0/8 - - name: DATABASE_NAME - value: shop-production - - name: S3_ENDPOINT - value: https://s3.example.com - - name: MAILER_FORCE_WHITELIST - value: "false" - - name: DATABASE_USER - value: shop-production - - name: DATABASE_PORT - value: "5432" - - name: MESSENGER_TRANSPORT_DSN - value: amqp://guest:guest@rabbitmq:5672/%2f/messages - - name: REDIS_PREFIX - value: shop-production - - name: DATABASE_PASSWORD - value: test-db-password - - name: DATABASE_HOST - value: 10.0.0.100 - - name: ELASTIC_SEARCH_INDEX_PREFIX - value: shop-production - - name: S3_SECRET - value: test-s3-secret - - name: MAILER_DSN - value: smtp://mailhog:1025 - - name: S3_BUCKET_NAME - value: shop-production - - name: S3_ACCESS_KEY - value: shop-production - - name: APP_SECRET - value: test-app-secret-key - image: v2.5.0 - imagePullPolicy: IfNotPresent - lifecycle: - preStop: - exec: - command: - - sleep - - "5" - name: cron - securityContext: - runAsUser: 0 - volumeMounts: - - mountPath: /var/www/html/config/domains_urls.yaml - name: domains-urls - subPath: domains_urls.yaml - - mountPath: /var/spool/cron/template - name: cron-list - subPath: cron - - mountPath: /root/.project_env.sh - name: cron-env - subPath: .project_env.sh - - mountPath: /var/www/html/config/frontend-api - name: fe-api-keys-volume - readOnly: true - workingDir: /var/www/html - imagePullSecrets: - - name: dockerregistry - tolerations: - - effect: NoSchedule - key: workload - operator: Equal - value: background - volumes: - - configMap: - name: domains-urls-47t6ghttc4 - name: domains-urls - - configMap: - name: cron-list - name: cron-list - - configMap: - name: cron-env - name: cron-env - - name: fe-api-keys-volume - secret: - defaultMode: 420 - secretName: fe-api-keys diff --git a/tests/scenarios/production-with-cloudflare/expected/horizontalPodAutoscaler.yaml b/tests/scenarios/production-with-cloudflare/expected/horizontalPodAutoscaler.yaml deleted file mode 100644 index 13e1051..0000000 --- a/tests/scenarios/production-with-cloudflare/expected/horizontalPodAutoscaler.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: webserver-php-fpm - namespace: "shop-production" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: webserver-php-fpm - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: ContainerResource - containerResource: - name: cpu - container: php-fpm - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/production-with-cloudflare/expected/horizontalStorefrontAutoscaler.yaml b/tests/scenarios/production-with-cloudflare/expected/horizontalStorefrontAutoscaler.yaml deleted file mode 100644 index 2ef81ef..0000000 --- a/tests/scenarios/production-with-cloudflare/expected/horizontalStorefrontAutoscaler.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: storefront - namespace: "shop-production" -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: storefront - minReplicas: 2 - maxReplicas: 3 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 120 diff --git a/tests/scenarios/production-with-cloudflare/expected/migrate-continuous-deploy.yaml b/tests/scenarios/production-with-cloudflare/expected/migrate-continuous-deploy.yaml index c4225cb..da3b222 100644 --- a/tests/scenarios/production-with-cloudflare/expected/migrate-continuous-deploy.yaml +++ b/tests/scenarios/production-with-cloudflare/expected/migrate-continuous-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: shop-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -353,19 +348,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -402,6 +384,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -447,22 +442,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy-with-demo-data.yaml b/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy-with-demo-data.yaml index 780ffd8..12318ab 100644 --- a/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy-with-demo-data.yaml +++ b/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy-with-demo-data.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: shop-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -353,19 +348,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -402,6 +384,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -447,22 +442,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy.yaml b/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy.yaml index 3e0da2b..6cd76e8 100644 --- a/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy.yaml +++ b/tests/scenarios/production-with-cloudflare/expected/migrate-first-deploy.yaml @@ -1,9 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - name: shop-production ---- -apiVersion: v1 data: domains_urls.yaml: | domains_urls: @@ -353,19 +348,6 @@ spec: app: redis spec: containers: - - image: oliver006/redis_exporter - imagePullPolicy: Always - name: redis-exporter - ports: - - containerPort: 9121 - name: exporter - protocol: TCP - resources: - limits: - memory: 128Mi - requests: - cpu: 10m - memory: 128Mi - args: - /usr/local/etc/redis/redis.conf image: redis:7.4-alpine @@ -402,6 +384,19 @@ spec: - mountPath: /usr/local/etc/redis/redis.conf name: config subPath: redis.conf + - image: oliver006/redis_exporter + imagePullPolicy: Always + name: redis-exporter + ports: + - containerPort: 9121 + name: exporter + protocol: TCP + resources: + limits: + memory: 128Mi + requests: + cpu: 10m + memory: 128Mi volumes: - configMap: defaultMode: 493 @@ -447,22 +442,64 @@ spec: - name: RABBITMQ_DEFAULT_PASS value: rabbitmq-password image: rabbitmq:4.1-management-alpine + lifecycle: + preStop: + exec: + command: + - sh + - -c + - rabbitmqctl stop_app && sleep 5 + livenessProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 5 + periodSeconds: 30 + timeoutSeconds: 15 name: rabbitmq ports: - - containerPort: 15672 + - containerPort: 5672 name: rabbitmq protocol: TCP + - containerPort: 15672 + name: rabbitmq-management + protocol: TCP - containerPort: 15692 name: exporter protocol: TCP + readinessProbe: + exec: + command: + - rabbitmq-diagnostics + - -q + - check_running + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 resources: + limits: + memory: 512Mi requests: cpu: 20m + memory: 256Mi + startupProbe: + exec: + command: + - rabbitmq-diagnostics + - ping + failureThreshold: 30 + periodSeconds: 10 volumeMounts: - mountPath: /var/lib/rabbitmq name: rabbitmq-data imagePullSecrets: - name: dockerregistry + terminationGracePeriodSeconds: 90 + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate volumeClaimTemplates: - metadata: name: rabbitmq-data diff --git a/tests/scenarios/production-with-cloudflare/expected/namespace.yaml b/tests/scenarios/production-with-cloudflare/expected/namespace.yaml deleted file mode 100644 index b842341..0000000 --- a/tests/scenarios/production-with-cloudflare/expected/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "shop-production" diff --git a/tests/scenarios/production-with-cloudflare/expected/webserver.yaml b/tests/scenarios/production-with-cloudflare/expected/webserver.yaml index 3db750c..f816b14 100644 --- a/tests/scenarios/production-with-cloudflare/expected/webserver.yaml +++ b/tests/scenarios/production-with-cloudflare/expected/webserver.yaml @@ -1,7 +1,39 @@ apiVersion: v1 -kind: Namespace +data: + .project_env.sh: | + export ELASTICSEARCH_HOST='http://elasticsearch:9200' + export TRUSTED_PROXY='10.0.0.0/8' + export DATABASE_NAME='shop-production' + export S3_ENDPOINT='https://s3.example.com' + export MAILER_FORCE_WHITELIST='false' + export DATABASE_USER='shop-production' + export DATABASE_PORT='5432' + export MESSENGER_TRANSPORT_DSN='amqp://guest:guest@rabbitmq:5672/%2f/messages' + export REDIS_PREFIX='shop-production' + export DATABASE_PASSWORD='test-db-password' + export DATABASE_HOST='10.0.0.100' + export ELASTIC_SEARCH_INDEX_PREFIX='shop-production' + export S3_SECRET='test-s3-secret' + export MAILER_DSN='smtp://mailhog:1025' + export S3_BUCKET_NAME='shop-production' + export S3_ACCESS_KEY='shop-production' + export APP_SECRET='test-app-secret-key' +kind: ConfigMap metadata: - name: shop-production + name: cron-env + namespace: shop-production +--- +apiVersion: v1 +data: + cron: |+ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + */5 * * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing cron > /dev/null 2>&1 + 0 */2 * * * . /root/.project_env.sh && cd /var/www/html/ && ./phing feed-generator > /dev/null 2>&1 + +kind: ConfigMap +metadata: + name: cron-list + namespace: shop-production --- apiVersion: v1 data: @@ -88,8 +120,15 @@ data: root /var/www/html/web; location /health { - stub_status on; access_log off; + + include fastcgi_params; + fastcgi_read_timeout 3s; + fastcgi_param SCRIPT_FILENAME /ping; + fastcgi_param SCRIPT_NAME /ping; + fastcgi_param REQUEST_METHOD GET; + + fastcgi_pass php-upstream; } } @@ -317,6 +356,8 @@ data: [www] listen = 127.0.0.1:9000 + ping.path = /ping + ping.response = pong pm = dynamic pm.max_children = 20 @@ -379,6 +420,138 @@ spec: --- apiVersion: apps/v1 kind: Deployment +metadata: + labels: + app: cron + name: cron + namespace: shop-production +spec: + replicas: 1 + selector: + matchLabels: + app: cron + strategy: + type: Recreate + template: + metadata: + annotations: + logging/enabled: "true" + project/app: cron + project/environment: production + project/name: shop + labels: + app: cron + date: "1234567890" + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: workload + operator: In + values: + - background + weight: 100 + containers: + - args: + - | + ./phing warmup > /dev/null + # FIFO for logs rm -f /tmp/log-pipe && mkfifo /tmp/log-pipe && chmod 666 /tmp/log-pipe + # crontab crontab -u root /var/spool/cron/template + # run on backround stdbuf -o0 tail -n +1 -f /tmp/log-pipe & + exec crond -f || exec cron -f + command: + - /bin/sh + - -lc + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: shop-production + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "false" + - name: DATABASE_USER + value: shop-production + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: shop-production + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: shop-production + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: shop-production + - name: S3_ACCESS_KEY + value: shop-production + - name: APP_SECRET + value: test-app-secret-key + image: v2.5.0 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -lc + - | + ( ./bin/console deploy:cron:lock > /tmp/cron-lock.log 2>&1 || true ) & + ./bin/console deploy:cron:watch || true + name: cron + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml + - mountPath: /var/spool/cron/template + name: cron-list + subPath: cron + - mountPath: /root/.project_env.sh + name: cron-env + subPath: .project_env.sh + - mountPath: /var/www/html/config/frontend-api + name: fe-api-keys-volume + readOnly: true + workingDir: /var/www/html + imagePullSecrets: + - name: dockerregistry + terminationGracePeriodSeconds: 3000 + tolerations: + - effect: NoSchedule + key: workload + operator: Equal + value: background + volumes: + - configMap: + name: domains-urls-47t6ghttc4 + name: domains-urls + - configMap: + name: cron-list + name: cron-list + - configMap: + name: cron-env + name: cron-env + - name: fe-api-keys-volume + secret: + defaultMode: 420 + secretName: fe-api-keys +--- +apiVersion: apps/v1 +kind: Deployment metadata: name: storefront namespace: shop-production @@ -387,6 +560,11 @@ spec: selector: matchLabels: app: storefront + strategy: + rollingUpdate: + maxSurge: 50% + maxUnavailable: 0 + type: RollingUpdate template: metadata: annotations: @@ -426,33 +604,42 @@ spec: preStop: exec: command: - - sleep - - "10" + - /bin/sh + - -lc + - sleep 10 livenessProbe: + failureThreshold: 3 httpGet: path: /api/health port: 3000 - initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 2 name: storefront ports: - containerPort: 3000 name: storefront protocol: TCP readinessProbe: + failureThreshold: 1 httpGet: path: /api/health port: 3000 initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 3 + timeoutSeconds: 2 resources: limits: memory: 1.5Gi requests: cpu: 500m memory: 800Mi + startupProbe: + failureThreshold: 60 + httpGet: + path: /api/health + port: 3000 + periodSeconds: 2 + timeoutSeconds: 2 imagePullSecrets: - name: dockerregistry terminationGracePeriodSeconds: 60 @@ -472,7 +659,7 @@ spec: app: webserver-php-fpm strategy: rollingUpdate: - maxSurge: 1 + maxSurge: 50% maxUnavailable: 0 type: RollingUpdate template: @@ -547,19 +734,25 @@ spec: image: v2.5.0 imagePullPolicy: IfNotPresent lifecycle: - postStart: - exec: - command: - - /var/www/html/phing - - -S - - warmup preStop: exec: command: - - sh - - -c - - sleep 10 && kill -SIGQUIT 1 + - /bin/sh + - -lc + - sleep 10; kill -QUIT 1 || true + livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 10 + tcpSocket: + port: 9000 + timeoutSeconds: 2 name: php-fpm + readinessProbe: + initialDelaySeconds: 2 + periodSeconds: 5 + tcpSocket: + port: 9000 + timeoutSeconds: 2 resources: limits: memory: 2Gi @@ -591,23 +784,27 @@ spec: - -c - sleep 5 && /usr/sbin/nginx -s quit livenessProbe: + failureThreshold: 6 httpGet: path: /health - port: 80 + port: health initialDelaySeconds: 30 - periodSeconds: 5 - timeoutSeconds: 5 + periodSeconds: 10 + timeoutSeconds: 3 name: webserver ports: - containerPort: 8080 name: http + - containerPort: 80 + name: health readinessProbe: + failureThreshold: 3 httpGet: path: /health - port: 80 - initialDelaySeconds: 5 + port: health + initialDelaySeconds: 2 periodSeconds: 5 - timeoutSeconds: 5 + timeoutSeconds: 2 resources: limits: memory: 300Mi @@ -644,6 +841,53 @@ spec: - mountPath: /var/www/html/config/domains_urls.yaml name: domains-urls subPath: domains_urls.yaml + - command: + - /var/www/html/phing + - -S + - warmup + env: + - name: ELASTICSEARCH_HOST + value: http://elasticsearch:9200 + - name: TRUSTED_PROXY + value: 10.0.0.0/8 + - name: DATABASE_NAME + value: shop-production + - name: S3_ENDPOINT + value: https://s3.example.com + - name: MAILER_FORCE_WHITELIST + value: "false" + - name: DATABASE_USER + value: shop-production + - name: DATABASE_PORT + value: "5432" + - name: MESSENGER_TRANSPORT_DSN + value: amqp://guest:guest@rabbitmq:5672/%2f/messages + - name: REDIS_PREFIX + value: shop-production + - name: DATABASE_PASSWORD + value: test-db-password + - name: DATABASE_HOST + value: 10.0.0.100 + - name: ELASTIC_SEARCH_INDEX_PREFIX + value: shop-production + - name: S3_SECRET + value: test-s3-secret + - name: MAILER_DSN + value: smtp://mailhog:1025 + - name: S3_BUCKET_NAME + value: shop-production + - name: S3_ACCESS_KEY + value: shop-production + - name: APP_SECRET + value: test-app-secret-key + image: v2.5.0 + name: warmup + volumeMounts: + - mountPath: /var/www/html + name: source-codes + - mountPath: /var/www/html/config/domains_urls.yaml + name: domains-urls + subPath: domains_urls.yaml terminationGracePeriodSeconds: 120 volumes: - emptyDir: {} @@ -665,6 +909,89 @@ spec: defaultMode: 420 secretName: fe-api-keys --- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: storefront + namespace: shop-production +spec: + behavior: + scaleDown: + policies: + - periodSeconds: 60 + type: Pods + value: 1 + - periodSeconds: 60 + type: Percent + value: 30 + selectPolicy: Max + stabilizationWindowSeconds: 600 + scaleUp: + policies: + - periodSeconds: 60 + type: Pods + value: 2 + - periodSeconds: 60 + type: Percent + value: 50 + selectPolicy: Max + stabilizationWindowSeconds: 60 + maxReplicas: 3 + metrics: + - resource: + name: cpu + target: + averageUtilization: 120 + type: Utilization + type: Resource + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: storefront +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: webserver-php-fpm + namespace: shop-production +spec: + behavior: + scaleDown: + policies: + - periodSeconds: 60 + type: Pods + value: 1 + - periodSeconds: 60 + type: Percent + value: 30 + selectPolicy: Max + stabilizationWindowSeconds: 600 + scaleUp: + policies: + - periodSeconds: 60 + type: Pods + value: 2 + - periodSeconds: 60 + type: Percent + value: 50 + selectPolicy: Max + stabilizationWindowSeconds: 60 + maxReplicas: 3 + metrics: + - containerResource: + container: php-fpm + name: cpu + target: + averageUtilization: 120 + type: Utilization + type: ContainerResource + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: webserver-php-fpm +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: