Deploying 1C-Bitrix in Kubernetes

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Deploying 1C-Bitrix in Kubernetes

1C-Bitrix was not designed for container orchestration. Sessions in files, cache on disk, uploaded files in upload/, core in bitrix/ — all these are "stateful" artifacts that in Kubernetes require special handling. Nevertheless, the task is solvable, and heavily loaded Bitrix sites work in production k8s clusters.

Main Problems When Containerizing Bitrix

Sessions. By default, PHP stores sessions in /tmp of the container. With multiple pod replicas, different requests from one user land on different pods — the session is lost. Solution: switch session storage to Redis.

In Bitrix's .settings.php:

'session' => [
    'value' => [
        'mode' => 'separated',
        'handlers' => [
            'general' => [
                'type' => 'redis',
                'host' => 'redis-service',
                'port' => 6379,
            ],
        ],
    ],
],

Cache. CACHE_TYPE=A in components by default writes to bitrix/cache/. With multiple replicas, cache is not synchronized. Switch to Memcached or Redis:

'cache' => [
    'value' => [
        'type' => ['memcache' => 'memcache'],
        'memcache' => [
            'host' => 'memcached-service',
            'port' => 11211,
        ],
    ],
],

Files. The upload/ directory must be accessible to all pods. Use PersistentVolumeClaim with ReadWriteMany mode (NFS, CephFS, Longhorn in RWX mode).

License. Bitrix ties the license to an IP address or domain, not to a container MAC address. When deploying to the cloud, ensure the external IP is stable or the license is issued for the domain.

Structure of Kubernetes Manifests

namespace: bitrix-prod
├── Deployment: bitrix-app (PHP-FPM + Nginx sidecar)
├── Service: bitrix-app-svc
├── Ingress: bitrix-ingress (with TLS)
├── StatefulSet: redis (or Redis Operator)
├── StatefulSet: memcached
├── PersistentVolumeClaim: bitrix-upload (RWX)
├── ConfigMap: php-fpm-config
├── ConfigMap: nginx-config
└── Secret: db-credentials

Deployment for PHP-FPM:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: bitrix-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: bitrix-app
  template:
    spec:
      containers:
        - name: php-fpm
          image: registry.example.com/bitrix-app:1.2.3
          volumeMounts:
            - name: upload
              mountPath: /var/www/html/upload
            - name: php-fpm-config
              mountPath: /usr/local/etc/php-fpm.d/www.conf
              subPath: www.conf
          env:
            - name: DB_HOST
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: host
        - name: nginx
          image: nginx:1.25-alpine
          ports:
            - containerPort: 80
          volumeMounts:
            - name: upload
              mountPath: /var/www/html/upload
            - name: nginx-config
              mountPath: /etc/nginx/conf.d/default.conf
              subPath: default.conf
      volumes:
        - name: upload
          persistentVolumeClaim:
            claimName: bitrix-upload
        - name: php-fpm-config
          configMap:
            name: php-fpm-config
        - name: nginx-config
          configMap:
            name: nginx-config

Dockerfile for Bitrix Image

FROM php:8.2-fpm-bullseye

RUN apt-get update && apt-get install -y \
    libzip-dev libpng-dev libjpeg-dev libwebp-dev \
    && docker-php-ext-install pdo_mysql zip gd opcache

RUN pecl install redis && docker-php-ext-enable redis
RUN pecl install memcached && docker-php-ext-enable memcached

COPY php.ini /usr/local/etc/php/conf.d/99-bitrix.ini
COPY --chown=www-data:www-data . /var/www/html

# upload/ is mounted as PVC, so exclude from image
RUN rm -rf /var/www/html/upload

WORKDIR /var/www/html

Important: Bitrix code (bitrix/, local/, public php files) is baked into the image. upload/ is mounted externally via PVC. Updating the site = building a new image + rolling update of the Deployment.

Database Outside Kubernetes

It is not recommended to run MySQL/PostgreSQL database in k8s without specialized operators (Percona Operator, CloudNativePG). It's simpler to use managed solutions: AWS RDS, Yandex Cloud Managed MySQL, or a dedicated server outside the cluster. Bitrix connects via standard host and port through a Secret.

Horizontal Scaling

After solving session and cache issues, the Deployment scales with the command:

kubectl scale deployment bitrix-app --replicas=5

Or automatically via HorizontalPodAutoscaler:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: bitrix-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: bitrix-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

CI/CD Pipeline

git push → GitLab CI/CD:
  1. docker build -t registry/bitrix-app:${CI_COMMIT_SHA} .
  2. docker push registry/bitrix-app:${CI_COMMIT_SHA}
  3. kubectl set image deployment/bitrix-app php-fpm=registry/bitrix-app:${CI_COMMIT_SHA}
  4. kubectl rollout status deployment/bitrix-app

Rolling update replaces pods one by one — zero downtime on deployments.

Timeline

Stage Content Duration
Analysis and preparation Bitrix configuration audit, session/cache solution selection 2–3 days
Dockerfile + image Build, functionality verification 2–3 days
k8s manifests Deployment, Service, Ingress, PVC, ConfigMap, Secret 3–4 days
Redis/Memcached Deployment and session/cache configuration 1–2 days
CI/CD Build and deploy pipeline 2–3 days
Testing Load tests, sticky session verification 2–3 days

Total: 2–3 weeks for production environment. For dev/staging — faster.