DevOPS CI/CD kubernetes

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

1. Giới Thiệu

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. 
$ 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

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”
  2. Add existing GKE cluster
  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”
  4. Khi K8S cluster đã sẵn sàng, bạn cần chỉnh lại “base domain”, sau đó save lại.

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”
  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. 

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)

6.  Configure application

6.1 git push golang application

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.
  2. Kiểm tra Pipepines
  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

                                       Nhấn Subcribe                                                           Like Facebook 

Add Comment

Click here to post a comment