Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LAMP in Containers

LAMP in Containers

An exploration of converting a LAMP app to a multi tier container app.

Terrence Ryan

April 06, 2017
Tweet

More Decks by Terrence Ryan

Other Decks in Technology

Transcript

  1. ‹#› @tpryan Process • Create a server • Linux •

    Apache • PHP • MySQL • Get starting schema and content on it • Initialize system
  2. ‹#› @tpryan Create a Server # Request Machine gcloud compute

    instances create $(MYSQL_HOSTNAME) --zone $(ZONE) \ --machine-type "f1-micro" --image-family="debian-8" \ --image-project="debian-cloud" \ --tags "http-server","https-server" # Install Apache + PHP apt-get update -y apt-get install apache2 php5 curl php5-curl -y # Install MySQL and PHP libratries DEBIAN_FRONTEND=noninteractive \ apt-get -y install mysql-server mysql-client php5-mysqlnd php-pear -y /etc/init.d/apache2 restart
  3. ‹#› @tpryan Create a Server # Security routines DELETE FROM

    mysql.user WHERE User='root' AND Host = '$(MYSQL_HOSTNAME)'; SET PASSWORD FOR 'root'@'localhost' = '$(MYSQL_ROOTHASH)'; SET PASSWORD FOR 'root'@'127.0.0.1' = '$(MYSQL_ROOTHASH)'; SET PASSWORD FOR 'root'@'::1' = '$(MYSQL_ROOTHASH)'; FLUSH PRIVILEGES; mysql_secure_installation $(MYSQL_ROOTHASH) = SELECT PASSWORD('SuperSecureIPromise')
  4. ‹#› @tpryan Details Time to build ~ 2:30 Time to

    update ~ :10 Lines of config code 63 Monthly Cost of Solution ~$4.28
  5. ‹#› @tpryan Dockerfiles FROM mysql/mysql-server:5.6 ADD sql/load.sql /docker-entrypoint-initdb.d/load.sql EXPOSE 3306

    DB FROM httpd:2.4 COPY ui /usr/local/apache2/htdocs/ui COPY static /usr/local/apache2/htdocs/static UI FROM php:7.0-apache RUN apt-get update && apt-get install -y php5-mysqlnd RUN docker-php-ext-install mysqli RUN a2enmod rewrite && a2enmod headers && service apache2 restart COPY app/ /var/www/html/ API
  6. ‹#› @tpryan docker run --name=3tier_frontend -d -p 8080:80 3tier_frontend docker

    run --name=3tier_api --link 3tier_db:mysql -d -p 80:80 3tier_api Startup scripts docker run --name=3tier_db -d -p 3306:3306 3tier_db DB UI API
  7. ‹#› @tpryan Original UI var url = this.protocol + this.host

    + this.uri_location_list; var type = "POST"; if (location.id != 0){ url += location.id; type = "PUT"; } $.ajax({ url: url, type: type, data: location, success: successHandler, error: errorHandler }); UI
  8. ‹#› @tpryan But secretly the API didn’t really care. if

    ($post_vars['id'] == 0){ // INSERT SQL.. } else { // UPDATE SQL... } API
  9. ‹#› @tpryan So now this var url = this.protocol +

    this.host + this.uri_location_list; var type = "POST"; if (location.id != 0){ url += location.id; type = "PUT"; } $.ajax({ url: url, type: type, data: location, success: successHandler, error: errorHandler }); UI var url = this.protocol + this.host + this.uri_location_list; var type = "POST"; if (location.id != 0){ url += location.id; type = "PUT"; } $.ajax({ url: url, type: type, data: location, success: successHandler, error: errorHandler });
  10. ‹#› @tpryan Details Time to build ~ :08 (+2:30) Time

    to update ~ :21 + (:10) Lines of config code 95 Monthly Cost of Solution* ~$4.28
  11. ‹#› @tpryan # FRONTEND AND SERVICES FROM nginx-php-fpm COPY nginx.conf

    /etc/nginx/nginx.conf ADD www /var/www/ # API FROM php:7.0-apache RUN apt-get update && apt-get install -y php5-mysqlnd RUN docker-php-ext-install mysqli RUN a2enmod rewrite && a2enmod headers && service apache2 restart COPY app/ /var/www/html/
  12. ‹#› @tpryan Kubernetes • Container Orchestration System • Open Source

    • Started by Google • Contributed to by others
  13. ‹#› @tpryan Requirements • Kubernetes Cluster • Images hosted in

    repository • Multiple running containers for • API • UI • Single instance of • DB • Disk for • DB • Public IP and load balancers for • API • UI
  14. ‹#› @tpryan Create a Cluster # Request Cluster gcloud container

    clusters create $(CLUSTER) --num-nodes 2 \ --disk-size=200 —machine-type="g1-small"
  15. ‹#› @tpryan Build and host images # Build API image

    docker build -t gcr.io/projectname/locations-api "containers/api/." # Push API to repository gcloud docker push gcr.io/projectname/locations-api # Build UI image docker build -t gcr.io/projectname/locations-ui "containers/ui/." # Push UI to repository gcloud docker push gcr.io/projectname/locations-ui # Build DB image docker build -t gcr.io/projectname/locations-db "containers/db/." # Push API to repository gcloud docker push gcr.io/projectname/locations-db
  16. ‹#› @tpryan Deployment apiVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend-deployment

    spec: replicas: 4 strategy: type: RollingUpdate template: metadata: labels: layer: ui spec: containers: - name: "frontend" image: "gcr.io/lamp-in-containers/locations-frontend" ports: - name: "http" containerPort: 80 protocol: TCP Pod Replica Set Deployment
  17. ‹#› @tpryan Stateful Set apiVersion: apps/v1beta1 kind: StatefulSet metadata: name:

    db-set spec: serviceName: "mysql" replicas: 1 template: metadata: labels: layer: db spec: terminationGracePeriodSeconds: 0 containers: - name: db image: "gcr.io/lamp-in-containers/locations-db" ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-pvc mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-pvc annotations: volume.alpha.kubernetes.io/storage-class: anything spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi Pod Persistent Volume Claim Stateful Set
  18. ‹#› @tpryan Deployment apiVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend-deployment

    spec: replicas: 4 strategy: type: RollingUpdate template: metadata: labels: layer: ui spec: containers: - name: "frontend" image: "gcr.io/lamp-in-containers/locations-frontend" ports: - name: "http" containerPort: 80 protocol: TCP Pod Label
  19. ‹#› @tpryan Service apiVersion: v1 kind: Service metadata: labels: name:

    frontend name: frontend spec: type: LoadBalancer ports: - port: 80 targetPort: 80 protocol: TCP selector: layer: ui Selector
  20. ‹#› @tpryan ui Pod ui deployment ui Pod ui Pod

    ui Pod ui service (public) api Pod api deployment api service (public) api Pod api Pod db statefulset db service (private) db Pod
  21. ‹#› @tpryan Details Time to build ~ 4:30 Time to

    update ~ :24 Lines of config code 266 Monthly Cost of Solution* ~$43.63
  22. ‹#› @tpryan DB API UI Managed SQL File Storage Leave

    on Kubernetes Switch to App Engine flexible
  23. ‹#› @tpryan Details Time to build ~ 8:00 Time to

    update ~ 5:00 Lines of config code 66 Monthly Cost of Solution ~$47.83