SlideShare a Scribd company logo
Scaleable PHP applications in
Kubernetes
Robert Lemke
Robert Lemke
Flownative Managing Partner
Neos CMS Project Founder
Robert Lemke
Flownative Managing Partner
Neos CMS Project Founder
Scaleable PHP Applications in Kubernetes
Intro | Discussion
Should I use
Kubernetes?
it depends
Automation and
Developer Experience
IaC
GitOps
agile
DX
UX
Challenges
security
expertise
complexity
What does it take to
run a PHP application
in Kubernetes?
Application
Architecture
Scaleable PHP Applications in Kubernetes
Scaleable PHP Applications in Kubernetes
Building Application
Artifacts
FROM scratch
MAINTAINER Flownative <support@flownative.com>
VOLUME /build
COPY DistributionPackages /build/DistributionPackages
COPY Packages/Framework /build/Packages/Framework
COPY Packages/Libraries /build/Packages/Libraries
COPY Packages/Application /build/Packages/Application
COPY bin /build/bin
COPY Web /build/Web
COPY flow /build/flow
COPY composer.json /build/composer.json
COPY composer.lock /build/composer.lock
COPY Configuration /build/Configuration
COPY beach* /build/
FROM scratch alpine:latest
MAINTAINER Flownative <support@flownative.com>
VOLUME /build
COPY DistributionPackages /build/DistributionPackages
COPY Packages/Framework /build/Packages/Framework
COPY Packages/Libraries /build/Packages/Libraries
COPY Packages/Application /build/Packages/Application
COPY bin /build/bin
COPY Web /build/Web
COPY flow /build/flow
COPY composer.json /build/composer.json
COPY composer.lock /build/composer.lock
COPY Configuration /build/Configuration
COPY beach* /build/
name: Build
on:
push:
branches-ignore:
- '**'
tags:
- 'v*.*.*'
jobs:
build:
runs-on: ubuntu-latest
steps:
# see https:
/
/
github.com/shivammathur/setup-php#bookmark-versioning)
- uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- uses: actions/checkout@v2
with:
ref: main
fetch-depth: 100
- name: Determine latest version
id: latest_version
uses: flownative/action-git-latest-release@master
- uses: actions/checkout@v2
with:
ref: ${{ steps.latest_version.outputs.tag }}
fetch-depth: 100
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
flavor: |
latest=true
images: |
europe-docker.pkg.dev/flownative/beach/beach-controlpanel
labels: |
org.opencontainers.image.title=Beach Control Panel
org.opencontainers.image.description=Docker image providing the Beach Contro
org.opencontainers.image.licenses=proprietary
org.opencontainers.image.vendor=Flownative GmbH
org.opencontainers.image.version=${{ steps.latest_version.outputs.version }}
tags: |
type=semver,pattern={{major}},value=${{ steps.latest_version.outputs.version
type=semver,pattern={{major}}.{{minor}},value=${{ steps.latest_version.outpu
type=semver,pattern={{version}},value=${{ steps.latest_version.outputs.versi
- name: Set up QEMU
id: qemu
europe-docker.pkg.dev/flownative/beach/beach-controlpanel
labels: |
org.opencontainers.image.title=Beach Control Panel
org.opencontainers.image.description=Docker image providing the Beach Contro
org.opencontainers.image.licenses=proprietary
org.opencontainers.image.vendor=Flownative GmbH
org.opencontainers.image.version=${{ steps.latest_version.outputs.version }}
tags: |
type=semver,pattern={{major}},value=${{ steps.latest_version.outputs.version
type=semver,pattern={{major}}.{{minor}},value=${{ steps.latest_version.outpu
type=semver,pattern={{version}},value=${{ steps.latest_version.outputs.versi
- name: Set up QEMU
id: qemu
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: Login to Google Artifacts Registry
uses: docker/login-action@v1
with:
registry: europe-docker.pkg.dev/flownative/beach
username: '_json_key'
password: ${{ secrets.GOOGLE_ARTIFACTS_PASSWORD_BEACH }}
id: composer-cache
uses: actions/cache@v2
with:
path: Packages
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
php-
- name: Add SSH key
uses: webfactory/ssh-agent@v0.5.4
with:
ssh-private-key: ${{ secrets.FLOWNATIVE_BOT_SSH_PRIVATE_KEY }}
- name: Install Dependencies
env:
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH_JSON }}
run: composer install -q
-
-
no-ansi
-
-
no-dev
-
-
no-interaction
-
-
no-progress
-
-
opt
- name: Build Docker image
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Google Cloud
https://cloud.google.com/artifact-registry/
Harbor
https://goharbor.io
Container
Docker Images
Pod
Structure
Base Image
- standards and tooling for other images
- common tools for application usage
👉 create your own base image
👉 reduce to a minimum, but not less
Which OS?
Alpine Linux
- smaller
fi
lesystem footprint
- more secure?
- only relevant in container context
- uses musl instead of glibc 🐛
Which OS?
Debian
- larger
fi
lesystem footprint
- well-established security team
- wide-spread, therefore more
fi
rst-hand
experience
- high compatibility due to glibc
Which OS?
👉 You need to feel comfortable working
with the OS and it must support all the
software you want to install
0
30
60
90
120
ubuntu:jammy debian:bullseye bitnami/minideb:bullseye alpine:latest
5,29 MB
72 MB
118 MB
69 MB
Does the image size
matter?
Due to layering not so much if most
containers use the same base image
dive
https://github.com/wagoodman/dive
Nightly Rebuilds
🙄
Nightly Rebuilds
😮
Build Cascade
announce:
runs-on: ubuntu-latest
needs: build
steps:
- name: Dispatch to beach-php
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.FLOWNATIVE_BOT_TOKEN }}
repository: flownative/docker-beach-php
event-type: php-images-built
client-payload: '{"image_name": "flownative/docker-php/php"}'
Build Cascade
name: Build Docker images
on:
repository_dispatch:
types: [php-images-built]
push:
branches-ignore:
- '**'
tags:
- 'v*.*.*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
fl
ownative/docker-php
https://github.com/flownative/?q=docker-
More image security
- don't run as root (use SecurityContext)
- disable privilege escalation
- automatically scan images
- redeploy automatically, frequently
- only include minimal amount of
software – do you really need a shell?
Deployment
Scaleable PHP Applications in Kubernetes
Scaleable PHP Applications in Kubernetes
Deployment
Strategies
Recreate
Recreate
Rollout
Rollout
Rollout
Rollout
Rollout
Blue / Green
Blue / Green
Blue / Green
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo-frontend
namespace: podinfo
spec:
selector:
matchLabels:
app.kubernetes.io/name: podinfo-frontend
template:
metadata:
labels:
app.kubernetes.io/name: podinfo-frontend
spec:
containers:
- name: podinfo
image: ghcr.io/stefanprodan/podinfo:6.2.0
command:
- ./podinfo
-
-
-
port=9898
spec:
containers:
- name: podinfo
image: ghcr.io/stefanprodan/podinfo:6.2.0
command:
- ./podinfo
-
-
-
port=9898
env:
- name: PODINFO_BACKEND_URL
value: http:
/
/
backend-podinfo:9898/echo
ports:
- containerPort: 9898
name: http
protocol: TCP
resources:
requests:
cpu: 50m
memory: 16Mi
limits:
cpu: 1
memory: 100Mi
Helm
https://helm.sh
Separate Pods
Frontend, Backend, Worker, Cron, …
Use Jobs for Warm Up
Container start-up time can be critical.
Helm hooks can be one solution.
Scaling
What to scale?
What about sessions, database, queues?
How quickly does your app start?
Test Performance
k6
https://k6.io/open-source
Storage
Object / Persistent
Prefer object storage, key / value storage,
database where possible.
Avoid traditional
fi
les (persistent
volumes).
Persistent Volumes
- vs. Ephemeral Volumes
- Storage Classes
- dynamic provisioning
- Container Storage Interface drivers
Persistent Volumes
- vs. Ephemeral Volumes
- Storage Classes
- dynamic provisioning
- Container Storage Interface drivers
- ReadWriteOnce vs ReadWriteMany
GlusterFS / Ceph
- distributed persistent storage systems
- GlusterFS: network
fi
le system
- Ceph: object storage
Databases
Latencies and clusters
Database in K8s?
probably not (yet)
Postgres Operator
https://github.com/zalando/postgres-operator
Monitoring and
Logging
Centralize logs or you
won't have logs.
Scaleable PHP Applications in Kubernetes
Loki
https://grafana.com/docs/loki/latest/clients/promtail
Promtail
https://grafana.com/docs/loki/latest/clients/promtail
Prometheus
https://prometheus.io
Scaleable PHP Applications in Kubernetes
Running Kubernetes
Self-Managed
Bare Matal
Virtual Machine
Managed Control Plane
Rancher
https://www.rancher.com/
How do I …?
Can I …?
With K8s, how does …?
robert@
fl
ownative.com
www.
fl
ownative.com
@robertlemke
@robert@
fl
ownative.social
Your thoughts?
Bonus: Base Image
Scaleable PHP Applications in Kubernetes
FROM bitnami/minideb:bullseye
LABEL org.opencontainers.image.authors="Robert Lemke <robert@flownative.com>"
ARG BUILD_DATE
LABEL com.flownative.base-image-build-date=$BUILD_DATE
ENV FLOWNATIVE_LIB_PATH="/opt/flownative/lib" 
FLOWNATIVE_INIT_PATH="/opt/flownative/init" 
FLOWNATIVE_LOG_PATH="/opt/flownative/log" 
FLOWNATIVE_LOG_PATH_AND_FILENAME="/dev/stdout" 
SYSLOG_BASE_PATH="/opt/flownative/syslog-ng" 
LOGROTATE_BASE_PATH="/opt/flownative/logrotate" 
SUPERVISOR_BASE_PATH="/opt/flownative/supervisor" 
LOG_DEBUG=true
COPY
-
-
from=europe-docker.pkg.dev/flownative/docker/bash-library:1.13.4 /lib $FLOWNATIVE_LIB_PATH
COPY root-files /
RUN /build.sh
&
&
rm /build.sh
USER 1000
ENTRYPOINT ["/entrypoint.sh"]
CMD [ "run" ]
FROM europe-docker.pkg.dev/flownative/docker/base:bullseye
LABEL org.opencontainers.image.authors="Robert Lemke <robert@flownative.com>"
# -----------------------------------------------------------------------------
# PHP
# Latest versions: https:
/
/
www.php.net/downloads.php
ARG PHP_VERSION
ENV PHP_VERSION ${PHP_VERSION}
ENV PHP_BASE_PATH="/opt/flownative/php" 
PATH="/opt/flownative/php/bin:$PATH" 
LOG_DEBUG="false"
USER root
COPY root-files /
RUN export FLOWNATIVE_LOG_PATH_AND_FILENAME=/dev/stdout 
&
&
/build.sh init 
&
&
/build.sh prepare 
&
&
/build.sh build 
&
&
/build.sh build_extension vips 
&
&
/build.sh build_extension igbinary 
&
&
/build.sh disable_extension igbinary 
&
&
/build.sh build_extension imagick 
&
&
/build.sh build_extension yaml 
&
&
/build.sh build_extension phpredis 
&
&
/build.sh build_extension xdebug 
&
&
/build.sh disable_extension xdebug 
&
&
/build.sh build_extension ssh2 
&
&
/build.sh clean
USER 1000
EXPOSE 9000 9001
WORKDIR ${PHP_BASE_PATH}
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "run" ]
FROM europe-docker.pkg.dev/flownative/docker/base:bullseye
LABEL org.opencontainers.image.authors="Robert Lemke <robert@flownative.com>"
# -----------------------------------------------------------------------------
# PHP
# Latest versions: https:
/
/
www.php.net/downloads.php
ARG PHP_VERSION
ENV PHP_VERSION ${PHP_VERSION}
ENV PHP_BASE_PATH="/opt/flownative/php" 
PATH="/opt/flownative/php/bin:$PATH" 
LOG_DEBUG="false"
USER root
COPY root-files /
RUN export FLOWNATIVE_LOG_PATH_AND_FILENAME=/dev/stdout 
&
&
/build.sh init 
&
&
/build.sh prepare 
&
&
/build.sh build 
&
&
/build.sh build_extension vips 
&
&
/build.sh build_extension igbinary 
&
&
/build.sh disable_extension igbinary 
&
&
/build.sh build_extension imagick 
&
&
/build.sh build_extension yaml 
&
&
/build.sh build_extension phpredis 
&
&
/build.sh build_extension xdebug 
&
&
/build.sh disable_extension xdebug 
&
&
/build.sh build_extension ssh2 
&
&
/build.sh clean
USER 1000
EXPOSE 9000 9001
WORKDIR ${PHP_BASE_PATH}
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "run" ]
#
!
/bin/bash
# Load helper libraries
. "${FLOWNATIVE_LIB_PATH}/banner.sh"
. "${FLOWNATIVE_LIB_PATH}/log.sh"
. "${FLOWNATIVE_LIB_PATH}/packages.sh"
set -o errexit
set -o nounset
set -o pipefail
…
# ---------------------------------------------------------------------------------------
# Main routine
case $1 in
init)
banner_flownative 'PHP'
if [[ ! "${PHP_VERSION}" =~ ^7.[1-4]|^8.[0-2] ]]; then
error "🛠 Unsupported PHP version '${PHP_VERSION}'"
exit 1
fi
build_create_directories
;
;
prepare)
packages_install $(build_get_runtime_packages) 1>$(debug_device)
packages_install $(build_get_build_packages) 1>$(debug_device)
;
;
build)
build_compile_php
;
;
build_extension)
build_php_extension $2
;
;
disable_extension)
build_disable_php_extension $2
;
;
clean)
build_adjust_permissions
packages_remove $(build_get_build_packages) 1>$(debug_device)
packages_remove $(build_get_unnecessary_packages) 1>$(debug_device)
packages_remove_docs_and_caches 1>$(debug_device)
build_clean
;
;
esac
# ---------------------------------------------------------------------------------------
# build_compile_php() -
#
# @global PHP_BASE_PATH
# @return void
#
build_compile_php() {
local php_source_url
php_source_url="https:
/
/
github.com/php/php-src/archive/php-${PHP_VERSION}.tar.gz"
info "🛠 Downloading source code for PHP ${PHP_VERSION} from ${php_source_url}
.
.
.
"
with_backoff "curl -sSL ${php_source_url} -o php.tar.gz" "15"
|
|
(
error "Failed downloading PHP source from ${php_source_url}"
exit 1
)
mkdir -p "${PHP_BASE_PATH}/src"
tar -xf php.tar.gz -C "${PHP_BASE_PATH}/src"
-
-
strip-components=1
rm php.tar.gz*
cd "${PHP_BASE_PATH}/src"
info "🛠 Generating build configuration
.
.
.
"
./buildconf
-
-
force >$(debug_device)
if [[ ! -f configure ]]; then
error "🛠 Failed generating build configuration, 'configure' not found"
# shellcheck disable=SC2012
ls | output
exit 1
fi
# For GCC warning options see: https:
/
/
gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html
export CFLAGS='-Wno-deprecated-declarations -Wno-stringop-overflow -Wno-implicit-function-declaration'
if [[ "${PHP_VERSION}" =~ ^7.4 ]]; then
info "🛠 Running configure for PHP 7.4
.
.
.
"
./configure 
-
-
prefix=${PHP_BASE_PATH} 
-
-
with-config-file-path="${PHP_BASE_PATH}/etc" 
-
-
if [[ ! -f configure ]]; then
error "🛠 Failed generating build configuration, 'configure' not found"
# shellcheck disable=SC2012
ls | output
exit 1
fi
# For GCC warning options see: https:
/
/
gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html
export CFLAGS='-Wno-deprecated-declarations -Wno-stringop-overflow -Wno-implicit-function-declaration'
if [[ "${PHP_VERSION}" =~ ^7.4 ]]; then
info "🛠 Running configure for PHP 7.4
.
.
.
"
./configure 
-
-
prefix=${PHP_BASE_PATH} 
-
-
with-config-file-path="${PHP_BASE_PATH}/etc" 
-
-
with-config-file-scan-dir="${PHP_BASE_PATH}/etc/conf.d" 
-
-
disable-cgi 
-
-
enable-calendar 
-
-
enable-exif 
-
-
enable-fpm 
-
-
enable-ftp 
-
-
enable-gd 
-
-
enable-intl 
-
-
enable-mbstring 
-
-
enable-pcntl 
-
-
enable-soap 
-
-
enable-sockets 
-
-
with-curl 
-
-
with-freetype 
-
-
with-gmp 
-
-
with-jpeg 
-
-
with-mysqli 
-
-
with-openssl 
-
-
with-pdo-pgsql 
-
-
with-pdo-mysql 
-
-
with-readline 
-
-
with-sodium 
-
-
with-system-ciphers 
-
-
with-webp 
-
-
with-zip 
-
-
with-zlib 
-
-
without-pear

More Related Content

Similar to Scaleable PHP Applications in Kubernetes (20)

PDF
Kubernetes for Java Developers
Anthony Dahanne
 
PDF
Be a happier developer with Docker: Tricks of the trade
Nicola Paolucci
 
PDF
The Big Cloud native FaaS Lebowski
QAware GmbH
 
PDF
Using Docker For Development
Laura Frank Tacho
 
PPTX
K8s best practices from the field!
DoiT International
 
PDF
Be a Happier Developer with Docker: Tricks of the Trade
Docker, Inc.
 
PDF
Kubernetes One-Click Deployment: Hands-on Workshop (Mainz)
QAware GmbH
 
PPTX
HPE Storage KubeCon US 2018 Workshop
Michael Mattsson
 
PDF
Kubernetes laravel and kubernetes
William Stewart
 
PPTX
PHP on Heroku: Deploying and Scaling Apps in the Cloud
Salesforce Developers
 
PDF
State of Containers and the Convergence of HPC and BigData
inside-BigData.com
 
PDF
Containers, Docker, and Microservices: the Terrific Trio
Jérôme Petazzoni
 
PDF
Storage based on_openstack_mariocho
Mario Cho
 
PDF
Isn’t it Ironic that a Redfish is software defining you
Bruno Cornec
 
PPTX
What's New in Docker - February 2017
Patrick Chanezon
 
PPTX
Docker - Der Wal in der Kiste
Ulrich Krause
 
PDF
Containerization is more than the new Virtualization: enabling separation of ...
Jérôme Petazzoni
 
PDF
Docker module 1
Liang Bo
 
PDF
A DevOps guide to Kubernetes
Paul Czarkowski
 
PDF
Linux Containers and Docker SHARE.ORG Seattle 2015
Filipe Miranda
 
Kubernetes for Java Developers
Anthony Dahanne
 
Be a happier developer with Docker: Tricks of the trade
Nicola Paolucci
 
The Big Cloud native FaaS Lebowski
QAware GmbH
 
Using Docker For Development
Laura Frank Tacho
 
K8s best practices from the field!
DoiT International
 
Be a Happier Developer with Docker: Tricks of the Trade
Docker, Inc.
 
Kubernetes One-Click Deployment: Hands-on Workshop (Mainz)
QAware GmbH
 
HPE Storage KubeCon US 2018 Workshop
Michael Mattsson
 
Kubernetes laravel and kubernetes
William Stewart
 
PHP on Heroku: Deploying and Scaling Apps in the Cloud
Salesforce Developers
 
State of Containers and the Convergence of HPC and BigData
inside-BigData.com
 
Containers, Docker, and Microservices: the Terrific Trio
Jérôme Petazzoni
 
Storage based on_openstack_mariocho
Mario Cho
 
Isn’t it Ironic that a Redfish is software defining you
Bruno Cornec
 
What's New in Docker - February 2017
Patrick Chanezon
 
Docker - Der Wal in der Kiste
Ulrich Krause
 
Containerization is more than the new Virtualization: enabling separation of ...
Jérôme Petazzoni
 
Docker module 1
Liang Bo
 
A DevOps guide to Kubernetes
Paul Czarkowski
 
Linux Containers and Docker SHARE.ORG Seattle 2015
Filipe Miranda
 

More from Robert Lemke (20)

PDF
Neos Content Repository – Git for content
Robert Lemke
 
PDF
A General Purpose Docker Image for PHP
Robert Lemke
 
PDF
Flownative Beach - Neos Meetup Hamburg 2022
Robert Lemke
 
PDF
GitOps with Flux - IPC Munich 2022
Robert Lemke
 
PDF
OpenID Connect with Neos and Flow
Robert Lemke
 
PDF
Neos Conference 2019 Keynote
Robert Lemke
 
PDF
A practical introduction to Kubernetes (IPC 2018)
Robert Lemke
 
PDF
Neos Conference 2018 Welcome Keynote
Robert Lemke
 
PDF
A practical introduction to Event Sourcing and CQRS
Robert Lemke
 
PDF
Neos Conference 2017 Welcome Keynote
Robert Lemke
 
PDF
IPC16: A Practical Introduction to Kubernetes
Robert Lemke
 
PDF
IPC 2016: Content Strategy for Developers
Robert Lemke
 
PDF
Docker in Production - IPC 2016
Robert Lemke
 
PDF
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)
Robert Lemke
 
PDF
The Neos Brand (Inspiring Conference 2016)
Robert Lemke
 
PDF
Neos - past, present, future (Inspiring Conference 2016)
Robert Lemke
 
PDF
Meet Neos Nürnberg 2016: Ja ich will!
Robert Lemke
 
PDF
Meet Neos Nürnberg 2016: Hallo Neos!
Robert Lemke
 
PDF
Turning Neos inside out / React.js HH
Robert Lemke
 
PDF
Docker in Production - IPC 15 München
Robert Lemke
 
Neos Content Repository – Git for content
Robert Lemke
 
A General Purpose Docker Image for PHP
Robert Lemke
 
Flownative Beach - Neos Meetup Hamburg 2022
Robert Lemke
 
GitOps with Flux - IPC Munich 2022
Robert Lemke
 
OpenID Connect with Neos and Flow
Robert Lemke
 
Neos Conference 2019 Keynote
Robert Lemke
 
A practical introduction to Kubernetes (IPC 2018)
Robert Lemke
 
Neos Conference 2018 Welcome Keynote
Robert Lemke
 
A practical introduction to Event Sourcing and CQRS
Robert Lemke
 
Neos Conference 2017 Welcome Keynote
Robert Lemke
 
IPC16: A Practical Introduction to Kubernetes
Robert Lemke
 
IPC 2016: Content Strategy for Developers
Robert Lemke
 
Docker in Production - IPC 2016
Robert Lemke
 
Is this Open Source Thing Really Worth it? (IPC 2016 Berlin)
Robert Lemke
 
The Neos Brand (Inspiring Conference 2016)
Robert Lemke
 
Neos - past, present, future (Inspiring Conference 2016)
Robert Lemke
 
Meet Neos Nürnberg 2016: Ja ich will!
Robert Lemke
 
Meet Neos Nürnberg 2016: Hallo Neos!
Robert Lemke
 
Turning Neos inside out / React.js HH
Robert Lemke
 
Docker in Production - IPC 15 München
Robert Lemke
 
Ad

Recently uploaded (16)

PDF
GEO Strategy 2025: Complete Presentation Deck for AI-Powered Customer Acquisi...
Zam Man
 
PPTX
Birth-after-Previous-Caesarean-Birth (1).pptx
fermann1
 
PDF
The Internet of Things (IoT) refers to a vast network of interconnected devic...
chethana8182
 
PPTX
The Internet of Things (IoT) refers to a vast network of interconnected devic...
chethana8182
 
PPTX
InOffensive Security_cybersecurity2.pptx
wihib17507
 
PDF
How Much GB RAM Do You Need for Coding? 5 Powerful Reasons 8GB Is More Than E...
freeshopbudget
 
PPTX
Finally, My Best IPTV Provider That Understands Movie Lovers Experience IPTVG...
Rafael IPTV
 
PPTX
AI at Your Side: Boost Impact Without Losing the Human Touch (SXSW 2026 Meet ...
maytaldahan
 
PDF
UI/UX Developer Guide: Tools, Trends, and Tips for 2025
Penguin peak
 
PDF
AiDAC – Custody Platform Overview for Institutional Use.pdf
BobPesakovic
 
PPTX
The Monk and the Sadhurr and the story of how
BeshoyGirgis2
 
PPTX
Internet Basics for class ix. Unit I. Describe
ASHUTOSHKUMAR1131
 
PPTX
The Internet of Things (IoT) refers to a vast network of interconnected devic...
chethana8182
 
PPTX
MSadfadsfafdadfccadradfT_Presentation.pptx
pahalaedward2
 
PDF
The AI Trust Gap: Consumer Attitudes to AI-Generated Content
Exploding Topics
 
DOCX
An_Operating_System by chidi kingsley wo
kingsleywokocha4
 
GEO Strategy 2025: Complete Presentation Deck for AI-Powered Customer Acquisi...
Zam Man
 
Birth-after-Previous-Caesarean-Birth (1).pptx
fermann1
 
The Internet of Things (IoT) refers to a vast network of interconnected devic...
chethana8182
 
The Internet of Things (IoT) refers to a vast network of interconnected devic...
chethana8182
 
InOffensive Security_cybersecurity2.pptx
wihib17507
 
How Much GB RAM Do You Need for Coding? 5 Powerful Reasons 8GB Is More Than E...
freeshopbudget
 
Finally, My Best IPTV Provider That Understands Movie Lovers Experience IPTVG...
Rafael IPTV
 
AI at Your Side: Boost Impact Without Losing the Human Touch (SXSW 2026 Meet ...
maytaldahan
 
UI/UX Developer Guide: Tools, Trends, and Tips for 2025
Penguin peak
 
AiDAC – Custody Platform Overview for Institutional Use.pdf
BobPesakovic
 
The Monk and the Sadhurr and the story of how
BeshoyGirgis2
 
Internet Basics for class ix. Unit I. Describe
ASHUTOSHKUMAR1131
 
The Internet of Things (IoT) refers to a vast network of interconnected devic...
chethana8182
 
MSadfadsfafdadfccadradfT_Presentation.pptx
pahalaedward2
 
The AI Trust Gap: Consumer Attitudes to AI-Generated Content
Exploding Topics
 
An_Operating_System by chidi kingsley wo
kingsleywokocha4
 
Ad

Scaleable PHP Applications in Kubernetes

  • 1. Scaleable PHP applications in Kubernetes Robert Lemke
  • 2. Robert Lemke Flownative Managing Partner Neos CMS Project Founder
  • 3. Robert Lemke Flownative Managing Partner Neos CMS Project Founder
  • 9. What does it take to run a PHP application in Kubernetes?
  • 14. FROM scratch MAINTAINER Flownative <support@flownative.com> VOLUME /build COPY DistributionPackages /build/DistributionPackages COPY Packages/Framework /build/Packages/Framework COPY Packages/Libraries /build/Packages/Libraries COPY Packages/Application /build/Packages/Application COPY bin /build/bin COPY Web /build/Web COPY flow /build/flow COPY composer.json /build/composer.json COPY composer.lock /build/composer.lock COPY Configuration /build/Configuration COPY beach* /build/
  • 15. FROM scratch alpine:latest MAINTAINER Flownative <support@flownative.com> VOLUME /build COPY DistributionPackages /build/DistributionPackages COPY Packages/Framework /build/Packages/Framework COPY Packages/Libraries /build/Packages/Libraries COPY Packages/Application /build/Packages/Application COPY bin /build/bin COPY Web /build/Web COPY flow /build/flow COPY composer.json /build/composer.json COPY composer.lock /build/composer.lock COPY Configuration /build/Configuration COPY beach* /build/
  • 16. name: Build on: push: branches-ignore: - '**' tags: - 'v*.*.*' jobs: build: runs-on: ubuntu-latest steps: # see https: / / github.com/shivammathur/setup-php#bookmark-versioning) - uses: shivammathur/setup-php@v2 with: php-version: '8.1' - uses: actions/checkout@v2 with: ref: main fetch-depth: 100 - name: Determine latest version id: latest_version uses: flownative/action-git-latest-release@master
  • 17. - uses: actions/checkout@v2 with: ref: ${{ steps.latest_version.outputs.tag }} fetch-depth: 100 - name: Docker meta id: meta uses: docker/metadata-action@v3 with: flavor: | latest=true images: | europe-docker.pkg.dev/flownative/beach/beach-controlpanel labels: | org.opencontainers.image.title=Beach Control Panel org.opencontainers.image.description=Docker image providing the Beach Contro org.opencontainers.image.licenses=proprietary org.opencontainers.image.vendor=Flownative GmbH org.opencontainers.image.version=${{ steps.latest_version.outputs.version }} tags: | type=semver,pattern={{major}},value=${{ steps.latest_version.outputs.version type=semver,pattern={{major}}.{{minor}},value=${{ steps.latest_version.outpu type=semver,pattern={{version}},value=${{ steps.latest_version.outputs.versi - name: Set up QEMU id: qemu
  • 18. europe-docker.pkg.dev/flownative/beach/beach-controlpanel labels: | org.opencontainers.image.title=Beach Control Panel org.opencontainers.image.description=Docker image providing the Beach Contro org.opencontainers.image.licenses=proprietary org.opencontainers.image.vendor=Flownative GmbH org.opencontainers.image.version=${{ steps.latest_version.outputs.version }} tags: | type=semver,pattern={{major}},value=${{ steps.latest_version.outputs.version type=semver,pattern={{major}}.{{minor}},value=${{ steps.latest_version.outpu type=semver,pattern={{version}},value=${{ steps.latest_version.outputs.versi - name: Set up QEMU id: qemu uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v1 - name: Login to Google Artifacts Registry uses: docker/login-action@v1 with: registry: europe-docker.pkg.dev/flownative/beach username: '_json_key' password: ${{ secrets.GOOGLE_ARTIFACTS_PASSWORD_BEACH }}
  • 19. id: composer-cache uses: actions/cache@v2 with: path: Packages key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} restore-keys: | php- - name: Add SSH key uses: webfactory/ssh-agent@v0.5.4 with: ssh-private-key: ${{ secrets.FLOWNATIVE_BOT_SSH_PRIVATE_KEY }} - name: Install Dependencies env: COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH_JSON }} run: composer install -q - - no-ansi - - no-dev - - no-interaction - - no-progress - - opt - name: Build Docker image uses: docker/build-push-action@v2 with: context: . platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}
  • 24. Base Image - standards and tooling for other images - common tools for application usage 👉 create your own base image 👉 reduce to a minimum, but not less
  • 25. Which OS? Alpine Linux - smaller fi lesystem footprint - more secure? - only relevant in container context - uses musl instead of glibc 🐛
  • 26. Which OS? Debian - larger fi lesystem footprint - well-established security team - wide-spread, therefore more fi rst-hand experience - high compatibility due to glibc
  • 27. Which OS? 👉 You need to feel comfortable working with the OS and it must support all the software you want to install
  • 29. Does the image size matter? Due to layering not so much if most containers use the same base image
  • 33. Build Cascade announce: runs-on: ubuntu-latest needs: build steps: - name: Dispatch to beach-php uses: peter-evans/repository-dispatch@v1 with: token: ${{ secrets.FLOWNATIVE_BOT_TOKEN }} repository: flownative/docker-beach-php event-type: php-images-built client-payload: '{"image_name": "flownative/docker-php/php"}'
  • 34. Build Cascade name: Build Docker images on: repository_dispatch: types: [php-images-built] push: branches-ignore: - '**' tags: - 'v*.*.*' jobs: build: runs-on: ubuntu-latest strategy: matrix:
  • 36. More image security - don't run as root (use SecurityContext) - disable privilege escalation - automatically scan images - redeploy automatically, frequently - only include minimal amount of software – do you really need a shell?
  • 51. apiVersion: apps/v1 kind: Deployment metadata: name: podinfo-frontend namespace: podinfo spec: selector: matchLabels: app.kubernetes.io/name: podinfo-frontend template: metadata: labels: app.kubernetes.io/name: podinfo-frontend spec: containers: - name: podinfo image: ghcr.io/stefanprodan/podinfo:6.2.0 command: - ./podinfo - - - port=9898
  • 52. spec: containers: - name: podinfo image: ghcr.io/stefanprodan/podinfo:6.2.0 command: - ./podinfo - - - port=9898 env: - name: PODINFO_BACKEND_URL value: http: / / backend-podinfo:9898/echo ports: - containerPort: 9898 name: http protocol: TCP resources: requests: cpu: 50m memory: 16Mi limits: cpu: 1 memory: 100Mi
  • 54. Separate Pods Frontend, Backend, Worker, Cron, …
  • 55. Use Jobs for Warm Up Container start-up time can be critical. Helm hooks can be one solution.
  • 57. What to scale? What about sessions, database, queues? How quickly does your app start?
  • 61. Object / Persistent Prefer object storage, key / value storage, database where possible. Avoid traditional fi les (persistent volumes).
  • 62. Persistent Volumes - vs. Ephemeral Volumes - Storage Classes - dynamic provisioning - Container Storage Interface drivers
  • 63. Persistent Volumes - vs. Ephemeral Volumes - Storage Classes - dynamic provisioning - Container Storage Interface drivers - ReadWriteOnce vs ReadWriteMany
  • 64. GlusterFS / Ceph - distributed persistent storage systems - GlusterFS: network fi le system - Ceph: object storage
  • 70. Centralize logs or you won't have logs.
  • 79. How do I …? Can I …? With K8s, how does …?
  • 83. FROM bitnami/minideb:bullseye LABEL org.opencontainers.image.authors="Robert Lemke <robert@flownative.com>" ARG BUILD_DATE LABEL com.flownative.base-image-build-date=$BUILD_DATE ENV FLOWNATIVE_LIB_PATH="/opt/flownative/lib" FLOWNATIVE_INIT_PATH="/opt/flownative/init" FLOWNATIVE_LOG_PATH="/opt/flownative/log" FLOWNATIVE_LOG_PATH_AND_FILENAME="/dev/stdout" SYSLOG_BASE_PATH="/opt/flownative/syslog-ng" LOGROTATE_BASE_PATH="/opt/flownative/logrotate" SUPERVISOR_BASE_PATH="/opt/flownative/supervisor" LOG_DEBUG=true COPY - - from=europe-docker.pkg.dev/flownative/docker/bash-library:1.13.4 /lib $FLOWNATIVE_LIB_PATH COPY root-files / RUN /build.sh & & rm /build.sh USER 1000 ENTRYPOINT ["/entrypoint.sh"] CMD [ "run" ]
  • 84. FROM europe-docker.pkg.dev/flownative/docker/base:bullseye LABEL org.opencontainers.image.authors="Robert Lemke <robert@flownative.com>" # ----------------------------------------------------------------------------- # PHP # Latest versions: https: / / www.php.net/downloads.php ARG PHP_VERSION ENV PHP_VERSION ${PHP_VERSION} ENV PHP_BASE_PATH="/opt/flownative/php" PATH="/opt/flownative/php/bin:$PATH" LOG_DEBUG="false" USER root COPY root-files / RUN export FLOWNATIVE_LOG_PATH_AND_FILENAME=/dev/stdout & & /build.sh init & & /build.sh prepare & & /build.sh build & & /build.sh build_extension vips & & /build.sh build_extension igbinary & & /build.sh disable_extension igbinary & & /build.sh build_extension imagick & & /build.sh build_extension yaml & & /build.sh build_extension phpredis & & /build.sh build_extension xdebug & & /build.sh disable_extension xdebug & & /build.sh build_extension ssh2 & & /build.sh clean USER 1000 EXPOSE 9000 9001 WORKDIR ${PHP_BASE_PATH} ENTRYPOINT [ "/entrypoint.sh" ] CMD [ "run" ]
  • 85. FROM europe-docker.pkg.dev/flownative/docker/base:bullseye LABEL org.opencontainers.image.authors="Robert Lemke <robert@flownative.com>" # ----------------------------------------------------------------------------- # PHP # Latest versions: https: / / www.php.net/downloads.php ARG PHP_VERSION ENV PHP_VERSION ${PHP_VERSION} ENV PHP_BASE_PATH="/opt/flownative/php" PATH="/opt/flownative/php/bin:$PATH" LOG_DEBUG="false" USER root COPY root-files / RUN export FLOWNATIVE_LOG_PATH_AND_FILENAME=/dev/stdout & & /build.sh init & & /build.sh prepare & & /build.sh build & & /build.sh build_extension vips & & /build.sh build_extension igbinary & & /build.sh disable_extension igbinary & & /build.sh build_extension imagick & & /build.sh build_extension yaml & & /build.sh build_extension phpredis & & /build.sh build_extension xdebug & & /build.sh disable_extension xdebug & & /build.sh build_extension ssh2 & & /build.sh clean USER 1000 EXPOSE 9000 9001 WORKDIR ${PHP_BASE_PATH} ENTRYPOINT [ "/entrypoint.sh" ] CMD [ "run" ]
  • 86. # ! /bin/bash # Load helper libraries . "${FLOWNATIVE_LIB_PATH}/banner.sh" . "${FLOWNATIVE_LIB_PATH}/log.sh" . "${FLOWNATIVE_LIB_PATH}/packages.sh" set -o errexit set -o nounset set -o pipefail … # --------------------------------------------------------------------------------------- # Main routine case $1 in init) banner_flownative 'PHP' if [[ ! "${PHP_VERSION}" =~ ^7.[1-4]|^8.[0-2] ]]; then error "🛠 Unsupported PHP version '${PHP_VERSION}'" exit 1 fi build_create_directories ; ; prepare) packages_install $(build_get_runtime_packages) 1>$(debug_device) packages_install $(build_get_build_packages) 1>$(debug_device) ; ; build) build_compile_php ; ; build_extension) build_php_extension $2 ; ; disable_extension) build_disable_php_extension $2 ; ; clean) build_adjust_permissions packages_remove $(build_get_build_packages) 1>$(debug_device) packages_remove $(build_get_unnecessary_packages) 1>$(debug_device) packages_remove_docs_and_caches 1>$(debug_device) build_clean ; ; esac
  • 87. # --------------------------------------------------------------------------------------- # build_compile_php() - # # @global PHP_BASE_PATH # @return void # build_compile_php() { local php_source_url php_source_url="https: / / github.com/php/php-src/archive/php-${PHP_VERSION}.tar.gz" info "🛠 Downloading source code for PHP ${PHP_VERSION} from ${php_source_url} . . . " with_backoff "curl -sSL ${php_source_url} -o php.tar.gz" "15" | | ( error "Failed downloading PHP source from ${php_source_url}" exit 1 ) mkdir -p "${PHP_BASE_PATH}/src" tar -xf php.tar.gz -C "${PHP_BASE_PATH}/src" - - strip-components=1 rm php.tar.gz* cd "${PHP_BASE_PATH}/src" info "🛠 Generating build configuration . . . " ./buildconf - - force >$(debug_device) if [[ ! -f configure ]]; then error "🛠 Failed generating build configuration, 'configure' not found" # shellcheck disable=SC2012 ls | output exit 1 fi # For GCC warning options see: https: / / gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html export CFLAGS='-Wno-deprecated-declarations -Wno-stringop-overflow -Wno-implicit-function-declaration' if [[ "${PHP_VERSION}" =~ ^7.4 ]]; then info "🛠 Running configure for PHP 7.4 . . . " ./configure - - prefix=${PHP_BASE_PATH} - - with-config-file-path="${PHP_BASE_PATH}/etc" - -
  • 88. if [[ ! -f configure ]]; then error "🛠 Failed generating build configuration, 'configure' not found" # shellcheck disable=SC2012 ls | output exit 1 fi # For GCC warning options see: https: / / gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html export CFLAGS='-Wno-deprecated-declarations -Wno-stringop-overflow -Wno-implicit-function-declaration' if [[ "${PHP_VERSION}" =~ ^7.4 ]]; then info "🛠 Running configure for PHP 7.4 . . . " ./configure - - prefix=${PHP_BASE_PATH} - - with-config-file-path="${PHP_BASE_PATH}/etc" - - with-config-file-scan-dir="${PHP_BASE_PATH}/etc/conf.d" - - disable-cgi - - enable-calendar - - enable-exif - - enable-fpm - - enable-ftp - - enable-gd - - enable-intl - - enable-mbstring - - enable-pcntl - - enable-soap - - enable-sockets - - with-curl - - with-freetype - - with-gmp - - with-jpeg - - with-mysqli - - with-openssl - - with-pdo-pgsql - - with-pdo-mysql - - with-readline - - with-sodium - - with-system-ciphers - - with-webp - - with-zip - - with-zlib - - without-pear