DevOps CI/CD Kubernetes

Sử dụng CI/CD GitLab deploy Golang Application lên K8S Google Cloud

golang k8s

Trong bài này sẽ hướng dẫn bạn cách build, deploy và run một Golang web service đơn giản bằng việc sử dụng GitLab và GCP GKE/AWS EKS.  Kết hợp sử dụng GitLab CI để quản lý tiến trình CI/CD trở nên dễ dàng hơn. 

Trước khi bắt đầu, bạn cần chuẩn bị một số yêu cầu sau: 

2. Yêu cầu: 

  1. GitLab Account
  2. GCP Account (either one)
  3. AWS Account (either one)
  4. setup Ingress Controller và Cert-Manager trên k8s

3. Tạo Project

3.1 Tạo Project trên Gitlab thông qua Gitlab Web Portal  theo 9 bước sau: 

  1. Tạo một project mới theo link: https://gitlab.com/projects/new
  2. Đặt tên project
  3. Thêm mô tả cho project ( không bắt buộc)
  4. Chọn Visibility Level là Private hay Public.
  5. Chọn vào “Initialize repository with a README”, ở bước này sẽ sinh ra một file README.md trong project.
  6. Sau khi thực hiện xong các bước trên, bạn sẽ được chuyển hướng đến trang chứa project vừa tạo.
  7. Chọn vào “Clone button” và copy đường link https, tiến hành clone project về máy bằng git clone. golang k8s1
$ git clone https://gitlab.com/hounienlin/mysample.git
  1. Chuyển vào thư mục vừa clone về, và kiểm tra file README.md trên máy của bạn, để đảm bảo là chúng ta có clone source về đúng hay không . $ ls README.md
  2. OK, như vậy là chúng ta chuẩn bị xong, sẵn sàng để sang phần tiếp theo.

4. Thêm một Cluster GKE vào GitLab

Ở bước này, chúng ta sẽ thêm Cluster k8s vào Gitlab. Để hiểu hơn về bước này, các bạn có thể tham khảo ở đây:

https://docs.gitlab.com/ee/user/project/clusters/add_existing_cluster.html

golang k8s2

golang k8s3

for my case, I just type below
$ k get secret |grep gitlab
$ k describe secret gitlab-token
Name:         gitlab-token
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: gitlab
              kubernetes.io/service-account.uid: b63fb686-cba6-4abc-9f97-cd6aec3c87cc
Type:  kubernetes.io/service-account-token
Data
====
ca.crt:     1159 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzthisisafaketokenVpSWFdiTWpKUkhCY0hzSXNCaDdjdDZKbTB1WDVBZTBiWmw0RzgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImdpdGxhYi10b2tlbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJnaXRsYjdoueljmasdlj;oelkmjkldklje09uOELJIDELJDVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJiNjNmYjY4Ni1jYmE2LTRhYmMtOWY5Ny1jZDZhZWMzYzg3Y2MiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpnaXRsYWIifQ.RMwRA5WlbDtZ4udCijV2pXhll1ZTRnspQkr3_dD6AwxkvEblT4lEd2H2I4LU_hP6PIXRtNyvoaogZn7UEZQXmKfHnQFS334Ttjvg0LQn1mg6a06nVwOStBMxpbSB82EQirRHT2h1nyG8VAimsRYHp67sahZR3Oc79ALBAkr3NSwHrr-sYQSKuxnwLFe9cD1rt6mQZPztq3sgLakASWixyO1_ZiRGQD08VE3VzF5kVLPn2o7xk4V7r6D-pbYvbxCoAYuNiS6AiQfZK9L7sevVvdjlOkYJaBULzFdfH7eLyUGKzTMRiT99m6UbhGCxqZyJXKhACrMqgJZOHgeUpHHQgQ
  1. Click vào “Add Kubernetes Cluster”golang k8s4
  2. Add existing GKE cluster golang k8s5
  3. Điền vào các thông tin Kubernetes cluster name, API URL, CA Certificate, và service token. Click vào button “Add Kubernetes cluster” golang k8s6golang k8s7
  4. Khi K8S cluster đã sẵn sàng, bạn cần chỉnh lại “base domain”, sau đó save lại.
    golang k8s8

5. Thêm ingress controller và cert-manager vào GKE cluster

Nếu bạn chưa biết cách, tham khảo tại đây.

5.1 Thêm deploy token 

Đây là token dùng cho k8s pull docker image về từ Gitlab repository. 

  1. Kéo xuống phía gần cuối, click  vào settings/repository
  2. Tìm đến mục “Deploy tokens” , click vào nút Expand.
  3. Ở đây, chúng ta cần tạo thêm một “Deploy token”. Nhập vào Tên và tích vào “read_registry”. 
  4. Click vào “Create deploy token”golang k8s9
  5. [Lưu ý] Bạn phải lưu lại username, password, vì nó chỉ hiển thị 1 lần. Nếu mất, bạn phải tạo lại. golang k8s10

5.2 Thêm variables

  1. Click vào settings/CI/CD
  2. Chọn vào mục “Variables” > “Add Variable”
  3. Thêm 2 variables ( KUBEPULLPASS  là deploy token password, KUBEPULLUSER là deploy token name vừa tạo)golang k8s11

6.  Configure application

6.1 git push golang application

golang k8s12

6.2 Config Dockerfile

FROM golang:1.12-alpine
RUN apk add --no-cache git

# Set the Current Working Directory inside the container
WORKDIR /app/xff
# We want to populate the module cache based on the go.{mod,sum} files.
COPY go.mod .
#COPY go.sum .
RUN go mod download

COPY . .
# Build the Go app
RUN go build -o ./out/xff .

# This container exposes port 8080 to the outside world
EXPOSE 9000

# Run the binary program produced by `go install`
CMD ["./out/xff"]

6.3 Config main.go

package main

import (
    "log"
    "net/http"
    "strings"

    "github.com/sebest/xff"
)

func main() {
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        //ips := strings.Split(r.Header.Get("X-Forwarded-For"))
        xff := strings.Split(r.Header.Get("X-Forwarded-For"), ", ")
        log.Printf("xff: %+v", xff)
        w.Write([]byte("(v3) XFF IP is " + strings.Join(xff, ", ") + "\n"))
    })

    xffmw, _ := xff.Default()
    http.ListenAndServe(":8080", xffmw.Handler(handler))
}

6.4 Config k8s.yml

kind: Service
apiVersion: v1
metadata:
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "80"
  name: ${APP_NAME}
spec:
  selector:
    app: ${APP_LABEL}
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: ${APP_NAME}
  labels:
    app: ${APP_LABEL}
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ${APP_LABEL}
  template:
    metadata:
      labels:
        app: ${APP_LABEL}
    spec:
      imagePullSecrets:
      - name: gitlab-auth
      containers:
      - name: ${APP_NAME}
        image: "${DOCKER_IMAGE_TAG}"
        ports:
        - containerPort: 8080
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: ${APP_NAME}-cert
spec:
  secretName: production-auto-deploy-tls
  dnsNames:
  - ${DEPLOY_HOST}
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - ${DEPLOY_HOST}
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ${APP_NAME}-ingress
  annotations:
    service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: ${DEPLOY_HOST}
      http:
        paths:
          - backend:
              serviceName: ${APP_NAME}
              servicePort: 80
  tls:
  - hosts:
    - ${DEPLOY_HOST}
    secretName: production-auto-deploy-tls

Trong đó, các biến môi trường ${…} sẽ được cấu hình trong file gitlab-ci.yaml

6.5 Config gitlab-ci.yaml

Thay đổi “xxx.yourbasedomain”, phù hợp với domain của bạn.

stages:
  - build
  - deploy

variables:
  DOCKER_IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

build:
  stage: build
  image: docker:stable
  services:
    - docker:19-dind
  variables:
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2
    DOCKER_TLS_CERTDIR: ""
  before_script:
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
    - docker info
  script:
    - docker build -t $DOCKER_IMAGE_TAG .
    - docker push $DOCKER_IMAGE_TAG
deploy:
  stage: deploy
  variables:
    APP_NAME: production-xff
    APP_LABEL: production
    DEPLOY_HOST: xxx.yourbasedomain
  environment:
    name: production
    url: https://xxx.yourbasedomain
  image: roffe/kubectl:v1.13.0
  script:
    - kubectl delete --ignore-not-found=true secret gitlab-auth
    - kubectl create secret docker-registry gitlab-auth --docker-server=$CI_REGISTRY --docker-username=$KUBE_PULL_USER --docker-password=$KUBE_PULL_PASS
    - cat k8s.yml | envsubst | kubectl apply -f -
  only:
    - master

6.6 go.mod and go.sum

$ go mod init main.go
$ go build -o xff

6.7 push code

$ git add .
$ git commit -am "this is my demo"
$ git push 

7. Monitoring

  1. Deploy job sẽ được trigger tự động.golang k8s13
  2. Kiểm tra Pipepines golang k8s14
  3. Để xem chi tiết, bạn có thể click vào pipelines để thấy các output. 

 

        Nguồn:                  

congdonglinux.com

             Nhấn Subcribe để nhận thêm nhiều bài viết mới                              Like Facebook

                                       [maxbutton id=”2″ ]                                                           [maxbutton id=”3″ ] 

Đăng ký liền tay Nhận Ngay Bài Mới

Subscribe ngay

Cám ơn bạn đã đăng ký !

Lỗi đăng ký !

Add Comment

Click here to post a comment

Đăng ký liền tay
Nhận Ngay Bài Mới

Subscribe ngay

Cám ơn bạn đã đăng ký !

Lỗi đăng ký !