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.







