Kubernetes for PHP developers

Alessandro Lai / @AlessandroLai

PHPDay 2020 - September 8th 2020, Online

https://joind.in/talk/b0b64

Who am I?

Kubernetes: where it came from

Inspired by Google's Borg project (C++) https://en.wikipedia.org/wiki/Kubernetes#History

Kubernetes: basic structure

Main resources

Pod
ConfigMap Secret

Deployment
Job

Service

CronJob

Ingress

Ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-phpday-demo
  labels:
    conf: phpday
spec:
  rules:
    - host: my-phpday-demo.alessandrolai.dev
      http:
        paths:
          - path: /
            backend:
              serviceName: nginx
              servicePort: 80
  tls:
    - hosts:
        - my-phpday-demo.alessandrolai.dev

Service

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    conf: phpday
spec:
  ports:
    - port: 80
      name: nginx-web
  selector:
    conf: phpday
    app: my-phpday-demo

Deployment (1/2)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  labels: # ...
spec:
  selector:
    matchLabels:
      conf: phpday
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 50%
  template:
    metadata:
      labels:
        conf: phpday
        app: my-phpday-demo
    # ...

Deployment (2/2)

kind: Deployment
# ...
spec:
  template:
    # ...
    spec:
      containers:
      - image: docker.facile.it/my-phpday-demo/nginx-prod:abc123
        name: nginx
        ports:
        - containerPort: 80
      - image: docker.facile.it/my-phpday-demo/php-prod:abc123
        name: php
        env:
          - name: DATABASE_PASSWORD
            valueFrom:
              secretKeyRef:
                name: my-database
                key: password

Cron

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: prod-cron-hello-world
spec:
  schedule: "0 23 * * *"
  suspend: false
  successfulJobsHistoryLimit: 3
  jobTemplate:
    template:
      spec:
        template:
          spec:
            containers:
            - image: docker.facile.it/my-phpday-demo/php-prod:abc123
              command:
              - bin/console
              - # ...

Objective: CI/CD pipeline

Example of a build pipeline in GitLab CI

Deploy (?)

Deploy:
  stage: Deploy
  script:
  - kubectl set image deployment/very-simple-app php=$PHP_IMAGE 
  - kubectl rollout status deployment/very-simple-app
  only:
  - master

Result:

$ kubectl set image deployment/very-simple-app php="${!PHP_IMAGE_VAR}"
deployment "very-simple-app" images updated

$ kubectl rollout status deployment/very-simple-app
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 5 of 6 updated replicas are available...
deployment "very-simple-app" successfully rolled out
Helm logo
Cloud Native Computing Foundation logo

What Helm does:

  • Templating
  • Package manager (charts)
  • Deployer

Chart folder

Folder structure of an Helm chart from the demo
Example project on GitLab

Template example

{{- $host := $.Values.app.url | trimPrefix "https://" | quote -}}

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ $.Values.app.name }}-ingress
spec:
  rules:
    - host: {{ $host }}
      http:
        paths:
          - path: /
            backend:
              serviceName: {{ $.Values.nginx.name }}
              servicePort: {{ $.Values.nginx.port }}
  tls:
    - hosts:
        - {{ $host }}

values.yaml

app:
  name: phpday-demo
  env: ~
  url: ~

nginx:
  port: 80
  name: nginx
  image: ~
  resources:
    requests:
      memory: 16M
      cpu: 10m
    limits:
      memory: 32M
      cpu: 50m
php:
  name: php
  image: ~
  replicas: 2
  resources:
    requests:
      memory: 63M
      cpu: 25m
    limits:
      memory: 128M
      cpu: 250m

Local dump/test

helm-template: helm-template-prod helm-template-staging

helm-template-prod:
  rm -rf k8s/prod/*
  @docker-compose run --rm helm /bin/sh -c "
    helm template /var/www/phpday/charts/phpday-demo/ \
      --output-dir /var/www/phpday/k8s/prod \
      --set app.env=prod
      # ..."

helm-template-staging:
  rm -rf k8s/staging/*
  @docker-compose run --rm helm /bin/sh -c "
    helm template /var/www/phpday/charts/phpday-demo/ \
      --output-dir /var/www/phpday/k8s/staging \
      --set app.env=staging
      # ..."
I like to dump and commit Charts into the project for easier inspection and to leverage git diff as a refactoring tool

Helm in action

Deploy:
  stage: Deploy
  image: $CI_REGISTRY_IMAGE/helm:2
  script:
    - >
      helm upgrade \
        --install \
        --atomic \
        --namespace="$KUBE_NAMESPACE" \
        --set app.env="$CI_ENVIRONMENT_SLUG" \
        # ...
        "phpday-demo-$CI_ENVIRONMENT_SLUG" \
        charts/phpday-demo/

...and going forward? Per-branch deploys!

Environment listing in GitLab
Deploy review:
  extends:
    - .deploy_template
    - .review_template
  variables:
    APP_ENV: review
  environment:
    url: http://$CI_ENVIRONMENT_SLUG.phpday.demo/
    on_stop: Stop review

Stop review:
  stage: Stop
  when: manual
  extends:
    - .review_template
    - .helm_job
  environment:
    action: stop
  script:
    - >
      helm delete \
        --tiller-namespace="$KUBE_NAMESPACE" \
        "phpday-demo-$CI_ENVIRONMENT_NAME"

References

Joind.in link: https://joind.in/talk/b0b64

Questions?

Please rate my talk on Joind.in:
https://joind.in/talk/b0b64

Contacts