Make sure your shit works

DevOps Malaysia Meetup #3

18 September 2018

Kai Hendry

2

Who am I?

My homepage

1. Running Linux since 2000
2. Devops specialist
3. AWS Hero
4. Created my own Linux distro Webconverger
5. Golang and serverless fan boy
6. Interesting in networking (Mikrotik stuff)

3

#alwayslearning

4

Unee-T

version: '2'
services:
    bugzilla:
      image: uneet/bugzilla-customisation
      restart: on-failure
      ports:
        - 8081:80
      environment: # Setup by local .env file
            SES_SMTP_USERNAME: ${SES_SMTP_USERNAME}
            SES_SMTP_PASSWORD: ${SES_SMTP_PASSWORD}
            SES_VERIFIED_SENDER: ${SES_VERIFIED_SENDER}
            MYSQL_HOST: ${MYSQL_HOST}
            MYSQL_PORT: ${MYSQL_PORT}
            MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
            MYSQL_DATABASE: ${MYSQL_DATABASE}
            MYSQL_USER: ${MYSQL_USER}
            MYSQL_PASSWORD: ${MYSQL_PASSWORD}
            PARAMS_URL: ${PARAMS_URL}
      depends_on:
        - db
      volumes:
            - ./custom:/opt/bugzilla/template/en/custom
            - ./skin:/opt/bugzilla/skins/contrib/skin
            - ./extensions/UneeTBridge:/opt/bugzilla/extensions/UneeTBridge
      networks:
        - network

    apienroll:
      image: uneet/apienroll
      ports:
          - 4000:9000
      environment:
            MYSQL_HOST: ${MYSQL_HOST}
            MYSQL_USER: ${MYSQL_USER}
            MYSQL_PASSWORD: ${MYSQL_PASSWORD}
            API_ACCESS_TOKEN: ${API_ACCESS_TOKEN}
      networks:
            - network

    unit:
      image: uneet/unit
      ports:
          - 4001:9000
      environment:
            MYSQL_HOST: ${MYSQL_HOST}
            MYSQL_USER: ${MYSQL_USER}
            MYSQL_PASSWORD: ${MYSQL_PASSWORD}
            API_ACCESS_TOKEN: ${API_ACCESS_TOKEN}
      networks:
            - network

    invite:
      image: uneet/invite
      network_mode: host
      environment:
            MYSQL_HOST: ${MYSQL_HOST}
            MYSQL_USER: ${MYSQL_USER}
            MYSQL_PASSWORD: ${MYSQL_PASSWORD}
            API_ACCESS_TOKEN: ${API_ACCESS_TOKEN}
            CASE_HOST: http://127.0.0.1:3000

    db:
      image: mariadb
      ports:
        - 3306:3306
      environment:
            MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
            MYSQL_DATABASE: ${MYSQL_DATABASE}
            MYSQL_USER: ${MYSQL_USER}
            MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      volumes:
            - ./mariadb:/var/lib/mysql
            - ./sql:/docker-entrypoint-initdb.d
            - ./sql-conf.d:/etc/mysql/conf.d
      networks:
            - network

    adminer:
     image: adminer
     ports:
        - 8082:8080
     depends_on:
        - db
     networks:
        - network

networks:
    network:
        driver: bridge
5

Basics

Monitoring your application

6

Tools I use and recommend

7

Grafana

8

Postman

9

UI-licious

10

Prometheus

11

Alerting

12

CloudWatch

13

14

default Application code handlers

import (
    "fmt"
    "net/http"

    "github.com/apex/log"
)

func showversion(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%v, commit %v, built at %v", version, commit, date)
}

func fail(w http.ResponseWriter, r *http.Request) {
    log.Warn("forcing 5xx")
    http.Error(w, "5xx", http.StatusInternalServerError)
}

func (h handler) ping(w http.ResponseWriter, r *http.Request) {
    err := h.db.Ping()
    if err != nil {
        log.WithError(err).Error("failed to ping database")
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    fmt.Fprintf(w, "OK")
}
15

Golang CI/CD is quite awesome

16

Try do exercises if you work with other people

17

DevOps is actually quite complicated

Your job as always is to reduce complexity

18

Thank you