Skip to content

Repository files navigation

Kubernetes Deployment

How to install

  1. Install package composer require shopsys/deployment

  2. Copy deploy-project.sh into your project to app/deploy/deploy-project.sh

  3. Create or copy htpasswd file with login credentials to app/deploy/basicHttpAuth

    Default login for basicHttpAuth is username/password For info about how change http auth credentials see Change HTTP auth

  4. Copy nginx.yaml into your project to app/orchestration/kubernetes/configmap/nginx.yaml

  5. Update your gitlab-ci.yml

    • create new stage with name deploy:

      stages:
      - build
      - test
      - review
      + - deploy
      - service
    • Add new deploy template:

      .deploy: &deployimage:
      name: shopsys/kubernetes-buildpack:2.0stage: deploytags:
      - dockerrules:
      - if: '$CI_PIPELINE_SOURCE == "schedule"'when: neverscript:
      - docker create -ti --name image ${TAG} bash
      - docker cp image:/var/www/html/var/ ./
      - mkdir -p /root/.kube/ && echo "${KUBE_CONFIG}" > /root/.kube/config
      - chmod +x ./deploy/deploy-project.sh && ./deploy/deploy-project.sh deploy
    • Add new jobs for deploy devel and production:

      deploy:production:
      <<: *deployresource_group: deploy_productionvariables:
      KUBE_CONFIG: ${KUBE_CONFIG_PROD}needs:
      - buildrules:
      - if: '$CI_PIPELINE_SOURCE == "schedule"'when: never
      - if: '$CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH =~ /^master-.*$/'when: manualallow_failure: falseenvironment:
      name: productionurl: https://${DOMAIN_HOSTNAME_1}deploy:devel:
      <<: *deployresource_group: deploy_develvariables:
      KUBE_CONFIG: ${KUBE_CONFIG_DEVEL}needs:
      - build
      - test:standards
      - test:functional
      - test:acceptancerules:
      - if: '$CI_PIPELINE_SOURCE == "schedule"'when: never
      - if: '$CI_COMMIT_BRANCH == "devel" || $CI_COMMIT_BRANCH =~ /^devel-.*$/'environment:
      name: develurl: https://${DOMAIN_HOSTNAME_1}
  6. Set Environment variables to in Gitlab (Settings -> CI/CD -> Variables)

  7. Push changes and have fun

Environment Variables

Environment variables can be set in Gitlab (Settings -> CI/CD -> Variables)

If you want to define your custom variables see Define custom variables section

NameExampleDescriptionScope
DEPLOY_REGISTER_USERdeployCredentials for downloading docker images *1)All
DEPLOY_REGISTER_PASSWORD*******Credentials for downloading docker images *1)All
DISPLAY_FINAL_CONFIGURATION1 OR 0Display configurations after kubernetes scripts are preparedAll
RUNNING_PRODUCTION1 OR 0Enable/disable HTTP auth and mailer whitelistproduction/devel
FIRST_DEPLOY1 OR 0Set to 1 if you are deploying project instance first timeproduction/devel
DOMAIN_HOSTNAME_*example.comVariable contains URL address for accessing website. See Add more or less domainsproduction/devel
ELASTICSEARCH_URLusername:password@elasticsearchElasticsearch login URLAll
POSTGRES_DATABASE_IP_ADDRESS127.0.0.1Postgres host IP addressproduction/devel
POSTGRES_DATABASE_PORT5432Postgres portAll
POSTGRES_DATABASE_PASSWORD*******Postgres login passwordproduction/devel
PROJECT_NAMEproject-prodName of project (Used for namespace, prefixes and S3 bucket) - must be distinct for production/devel with prod/devel suffixproduction/devel
S3_API_HOSThttps://s3.vshosting.cloudS3 API HostAll
S3_API_USERNAMEs3userS3 API usernameAll
S3_API_PASSWORD*******S3 API passwordAll
APP_SECRET*******Used to add more entropy to security related operationsAll
RABBITMQ_DEFAULT_USERrabbitadminDefault user used for RabbitMQ and the management serviceAll
RABBITMQ_DEFAULT_PASS*******Password for the default RabbitMQ userAll
RABBITMQ_IP_WHITELIST123.456.123.422, 423.534.223.234IP Addresses (separated by comma) for which is the RabbitMQ Management accessibleAll
USING_CLOUDFLARE1 OR 0Set to 1 if your site is using Cloudflare (enables IP whitelisting)production/devel
MCP_INGRESS_ENABLED1 OR 0Set to 0 to disable the separate ingress publishing the MCP endpoints without HTTP basic auth (default: 1)production/devel
MCP_IP_WHITELIST203.0.113.0/24, 198.51.100.10/32VPN egress IP ranges allowed to access MCP; when empty, MCP access is not restricted by source IPproduction/devel

*1) Credentials can be generated in Gitlab (Settings -> Repository -> Deploy Tokens) with read_registry scope only

You can add your custom variables. Do not forget to edit your deploy-project.sh file

Customize deployment

You can override Kubernetes manifests by placing your custom manifests into app/orchestration/kubernetes/ in your project.

You need to mirror folders to be able to override manifests

Create new cron instance

  1. Create new Phing target that will run your cron:

     <targetname="cron-customers"description="....">
    <execexecutable="${path.php.executable}"passthru="true"checkreturn="true">
    <argvalue="${path.bin-console}" />
    <argvalue="shopsys:cron" />
    <argvalue="--instance-name=customers" />
    </exec>
    </target>
  2. Declare new cron to your deploy configuration file (deploy-project.sh):

    As a key there is used phing target that you created in step 1. and value represents crontab timer

     ...
    declare -A CRON_INSTANCES=(
    ["cron"]='*/5 * * * *'
    + ["cron-customers"]='*/5 * * * *'
    )
    ...

Add more or less domains

This example will work with 3 domains

  1. Create environment variable for every domain:

    NameValue
    DOMAIN_HOSTNAME_1mydomain.prod.shopsys.cloud
    DOMAIN_HOSTNAME_2sk.mydomain.prod.shopsys.cloud
    DOMAIN_HOSTNAME_3en.mydomain.prod.shopsys.cloud
  2. Edit your deploy-project.sh file:

    ...
    function deploy() {
    DOMAINS=(
    DOMAIN_HOSTNAME_1
    DOMAIN_HOSTNAME_2
    + DOMAIN_HOSTNAME_3
    )
    ...

Define custom variables

  1. Create Environment variable
  2. Edit your deploy-project.sh file:
    ...
    declare -A ENVIRONMENT_VARIABLES=(
    ["DATABASE_HOST"]=${POSTGRES_DATABASE_IP_ADDRESS}
    ["DATABASE_NAME"]=${PROJECT_NAME}
    ["DATABASE_PORT"]=${POSTGRES_DATABASE_PORT}
    )
    ...
    Left part is name of variable in application and right part is name of variable Gitlab.

Set custom Redis version

Add new variable to deploy-project.sh and specify your redis version

 ...
BASIC_AUTH_PATH="${BASE_PATH}/deploy/basicHttpAuth"
DEPLOY_TARGET_PATH="${BASE_PATH}/var/deployment/deploy"
+ REDIS_VERSION='redis:4.0-alpine'
function deploy() {
...

Enable Horizontal pod autoscaling

Add new variables to deploy-project.sh to enable pod autoscaling:

  • Enable this functionality:
    ...
    function deploy() {
    DOMAINS=(
    DOMAIN_HOSTNAME_1
    ...
    )
    + ENABLE_AUTOSCALING=true
    ...
  • If you need more replicas, then you can adjust those variables (default values are set to 2):
    • MIN_PHP_FPM_REPLICAS
    • MAX_PHP_FPM_REPLICAS
    • MIN_STOREFRONT_REPLICAS
    • MAX_STOREFRONT_REPLICAS

How to launch only some domains

Add to deploy-project.sh new array FORCE_HTTP_AUTH_IN_PRODUCTION with domains which should be not accessible without HTTP auth:

...
)
+ # This setting has no effect when `RUNNING_PRODUCTION` is set to `0`+ FORCE_HTTP_AUTH_IN_PRODUCTION=(+ DOMAIN_HOSTNAME_2+ )
declare -A ENVIRONMENT_VARIABLES=(
...

Change HTTP auth

  1. Generate new HTTP auth string (for example here), or by command htpasswd -nb username password
  2. Replace or add new HTTP auth string to basicHttpAuth
  3. Set new credentials to variable in deploy-project.sh
...
function deploy() {
DOMAINS=(
DOMAIN_HOSTNAME_1
...
)
+ HTTP_AUTH_CREDENTIALS="username:password"
...

Whitelist IP addresses

There are two ways to set whitelisted IP addresses.

WHITELIST_IPS env variable on CI

You can set sensitive whitelisted IPs in your env variable like this:

WHITELIST_IPS="8.8.8.8, 217.23.44.23, 93.111.234.111"

DEFAULT_WHITELIST_IPS env variable in deploy-project.sh

For non-sensitive IPs, that you want to share between all environments you can use DEFAULT_WHITELIST_IPS in deploy-project.sh like this:

# Some IP Another IP Some service
DEFAULT_WHITELIST_IPS="8.8.8.8, 217.23.44.23, 93.111.234.111"

Values from both variables (WHITELIST_IPS and DEFAULT_WHITELIST_IPS) will be merged and used in the final configuration.

Configure Cloudflare

If your site is using Cloudflare, you can restrict direct access and allow traffic only through Cloudflare:

  1. Enable Cloudflare protection by setting the environment variable USING_CLOUDFLARE=1.
  2. By default, ALL domains will be protected. If you need to exclude specific domains from Cloudflare protection (e.g., for direct access or testing), add them to the CLOUDFLARE_EXCLUDED_DOMAINS array:
    ...
    + CLOUDFLARE_EXCLUDED_DOMAINS=(+ DOMAIN_HOSTNAME_2 # This domain will not have Cloudflare IP restrictions+ )
    ...

This prevents users from bypassing Cloudflare by accessing your origin server directly.

Notify about deployment on Slack

You can enable automatic notification of your deployment directly into Slack channel. It has some features:

  1. Notify about starting of deployment with a preview of features

Notify about starting of deployment with preview of features

Tip

If you are using Jira and you use [ABC-123] in the commit message, it will automatically create a link to the URL that is specified by JIRA_URL environment variable

Tip

Script will exclude commits that contain !ignore keyword

  1. Notify about the end of deployment. There are two possible alerts - Success and Error

Notify about end of deployment

This script works only with Gitlab and Slack, but you can override deploy/slack-notification.py if you want to change behavior. For Slack, you have to create some Slack App with permissions (chat:write, chat:write.public).

There has to be set some environment variables list in the table bellow:

ENVIRONMENT VARIABLEAdditional information
CI_API_V4_URLAutomatic by Gitlab
CI_PROJECT_IDAutomatic by Gitlab
CI_JOB_URLAutomatic by Gitlab
CI_COMMIT_SHAAutomatic by Gitlab
API_TOKENToken for Gitlab API that has access to read deployments
JIRA_URLSet URL for link Jira ID to Jira.
SLACK_TOKENSlack Bot User OAuth Token
SLACK_CHANNELChannel ID to post messages into. This variable should be set only for production Environment
SLACK_DISABLE_CHANGESIf set to true, no message with changes will be posted

Run background jobs only on selected nodes

Backend pods such as RabbitMQ, Cron and Consumers can be run only on selected nodes. Those pods have already configured tolerations, so you can use taints to select nodes where those pods will be run.

Add taint to nodes where you want to run those pods

kubectl label nodes <node-name> workload=background
kubectl taint nodes <node-name> workload=background:NoSchedule

Other pods will run on other nodes without this taint.

About

Simplifies the deployment of the Shopsys Platform application in Kubernetes. It provides an intuitive set of tools and configurations, allowing you to seamlessly orchestrate and manage the deployment process.

Resources

Code of conduct

Stars

0 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages