Slide 1

Slide 1 text

From source code to Kubernetes, a Continuous Deployment tale.

Slide 2

Slide 2 text

$ whoami @agonzalezro

Slide 3

Slide 3 text

What’s CI?

Slide 4

Slide 4 text

Push git Generate Validate Build Test git commit ok goimports ok go vet ok sonar? ok ...

Slide 5

Slide 5 text

What’s Continuous Delivery & Continuous Deployment?

Slide 6

Slide 6 text

Merge git Generate Validate Build Test Create artifact Security Checks Deploy Clair Atomic scan Call it X ...

Slide 7

Slide 7 text

Once upon a time...

Slide 8

Slide 8 text

There was a prince, call him Go

Slide 9

Slide 9 text

main.go const message = "Hi Gophercon 2018!"

Slide 10

Slide 10 text

main.go const message = "Hi Gophercon 2018!" func mainHandler(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, message) }

Slide 11

Slide 11 text

main.go func mainHandler(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, message) } func main() { r := mux.NewRouter() r.HandleFunc("/", mainHandler)

Slide 12

Slide 12 text

main.go func mainHandler(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, message) } func main() { r := mux.NewRouter() r.HandleFunc("/", mainHandler) port := ":8081" if v, ok := os.LookupEnv("PORT"); ok { port = ":" + v }

Slide 13

Slide 13 text

main.go func main() { r := mux.NewRouter() r.HandleFunc("/", mainHandler) port := ":8081" if v, ok := os.LookupEnv("PORT"); ok { port = ":" + v } log.Println("Listening on " + port) log.Fatal(http.ListenAndServe(port, r)) }

Slide 14

Slide 14 text

$ go build . $ go test -v .

Slide 15

Slide 15 text

And there was a princess, call her Docker

Slide 16

Slide 16 text

Dockerfile FROM golang:1.10-alpine3.7 as builder

Slide 17

Slide 17 text

Dockerfile FROM golang:1.10-alpine3.7 as builder WORKDIR /go/src/github.com/gophercon RUN apk --no-cache add git RUN go get -u github.com/golang/dep/cmd/dep COPY Gopkg.lock Gopkg.toml ./ RUN dep ensure -vendor-only

Slide 18

Slide 18 text

Dockerfile FROM golang:1.10-alpine3.7 as builder ... COPY Gopkg.lock Gopkg.toml ./ RUN dep ensure -vendor-only COPY . ./

Slide 19

Slide 19 text

Dockerfile FROM golang:1.10-alpine3.7 as builder ... COPY Gopkg.lock Gopkg.toml ./ RUN dep ensure -vendor-only COPY . ./ RUN go build

Slide 20

Slide 20 text

Dockerfile FROM golang:1.10-alpine3.7 as builder ... COPY . ./ RUN go build FROM alpine:3.7

Slide 21

Slide 21 text

Dockerfile FROM golang:1.10-alpine3.7 as builder ... COPY . ./ RUN go build FROM alpine:3.7 COPY --from=builder /go/src/github.com/gophercon ./

Slide 22

Slide 22 text

Dockerfile FROM golang:1.10-alpine3.7 as builder ... COPY . ./ RUN go build FROM alpine:3.7 COPY --from=builder /go/src/github.com/gophercon ./ CMD ["./gophercon"]

Slide 23

Slide 23 text

$ docker build -t gophercon . $ docker run -d gophercon

Slide 24

Slide 24 text

They wanted to live together in a beautiful castle, they called it Kubernetes

Slide 25

Slide 25 text

pod.yaml apiVersion: v1 kind: Pod

Slide 26

Slide 26 text

pod.yaml apiVersion: v1 kind: Pod metadata: name: just-a-pod

Slide 27

Slide 27 text

pod.yaml apiVersion: v1 kind: Pod metadata: name: just-a-pod spec: containers: - name: gophercon image: agonzalezro/gophercon:latest

Slide 28

Slide 28 text

pod.yaml apiVersion: v1 kind: Pod metadata: name: just-a-pod spec: containers: - name: gophercon image: agonzalezro/gophercon:latest

Slide 29

Slide 29 text

$ kubectl apply pod.yaml just-a-pod

Slide 30

Slide 30 text

deployment.yaml apiVersion: apps/v1 kind: Deployment

Slide 31

Slide 31 text

deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: gophercon-deployment labels: app: gophercon

Slide 32

Slide 32 text

deployment.yaml ... spec: replicas: 2 selector: matchLabels: app: gophercon template: # pod here

Slide 33

Slide 33 text

deployment.yaml ... template: metadata: labels: app: gophercon spec: containers: - name: gophercon # Don't use latest at home! image: agonzalezro/gophercon:latest

Slide 34

Slide 34 text

$ kubectl apply deployment.yaml gophercon gophercon

Slide 35

Slide 35 text

$ kubectl apply deployment.yaml gophercon gophercon

Slide 36

Slide 36 text

service.yaml apiVersion: v1 kind: Service

Slide 37

Slide 37 text

service.yaml apiVersion: v1 kind: Service metadata: name: gophercon-service

Slide 38

Slide 38 text

service.yaml ... spec: type: LoadBalancer

Slide 39

Slide 39 text

service.yaml ... spec: type: LoadBalancer ports: - name: gophercon port: 80 targetPort: 8081 protocol: TCP selector: app: gophercon

Slide 40

Slide 40 text

$ kubectl apply service.yaml gophercon gophercon

Slide 41

Slide 41 text

And we are going to help them with CI/CD

Slide 42

Slide 42 text

Adventure demo time!

Slide 43

Slide 43 text

github.com/agonzalezro/gophercon

Slide 44

Slide 44 text

# We are hiring! # Thanks! @agonzalezro

Slide 45

Slide 45 text

1. Only deploy if tested 2. Vulnerability scanner 3. Repo should ping CI, CI should deploy to k8s

Slide 46

Slide 46 text

$ helm install -f hack/values.yaml stable/jenkins NAME: zooming-wildebeest LAST DEPLOYED: Sat Jun 9 22:27:22 2018 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Secret

Slide 47

Slide 47 text

Notes The PR could be deployed in some environment pre-merging it. Secrets and configs