cicd

定义需要部署的资源
K8S
Kustomization 方式部署
deployment.yaml
定义一组 pod 的资源,可以由多个 pod 组成容器组,不过一般不建议这么做,而是各个服务独立开来
主要定义的资源

  • image 使用的镜像 (从公司 harbor 读取)
  • env 环境变量 (consul 的地址和 token)
  • ports 对外暴露服务的端口
  • resources 资源限制 (hpa 扩容的依据)
  • readinessProbe,livenessProbe 就绪探针和存活探针(K8S 重启服务和滚动更新的依据)
    就绪探针和存活探针
    就绪探针:K8S 会定时的访问提供的端口(TCP)或 URI(HTTP)确保服务以及就绪,将就绪的服务加入到负载均衡,提供外部或其他服务访问
    存活探针:K8S 会定时的访问提供的端口(TCP)或 URI(HTTP)确保服务以及就绪,将非存活的服务踢出负载均衡

    apiVersion: apps/v1
    
    kind: Deployment
    
    metadata:
    
      name: sc
    
      namespace: cs-hw
    
    spec:
    
      replicas: 1
    
      selector:
    
        matchLabels:
    
          app: sc
    
      template:
    
        metadata:
    
          labels:
    
            app: sc
    
        spec:
    
          containers:
    
            - name: sc
    
              image: registry.intsig.net/cs_hw/sc:latest
    
              imagePullPolicy: Always
    
              env:
    
                - name: KRATOS_CONSUL_ADDRESS
    
                  value: 10.2.1.176:8500
    
                - name: KRATOS_CONSUL_TOKEN
    
                  value: 335f912a-3403-bf1b-c127-af66e3cdd899
    
                - name: KRATOS_NODE_IP
    
                  valueFrom:
    
                    fieldRef:
    
                      fieldPath: status.hostIP
    
              ports:
    
                - containerPort: 8000
    
                - containerPort: 9000
    
              resources:
    
                limits:
    
                  cpu: "500m"
    
                  memory: "1Gi"
    
              livenessProbe:
    
                tcpSocket:
    
                  port: 9000
    
              readinessProbe:
    
                tcpSocket:
    
                  port: 9000
    
          restartPolicy: Always

    service.yaml
    定义对外暴露服务的方式
    主要定义的资源

  • 服务类型
  • port 暴露的端口,选项 targetPort (容器端口)不填默认为 port
  • selector 选择服务对应的 deployment

    apiVersion: v1
    
    kind: Service
    
    metadata:
    
      name: sc
    
      namespace: cs-hw
    
    spec:
    
      type: ClusterIP
    
      ports:
    
        - port: 8000
    
          name: http
    
        - port: 9000
    
          name: grpc
    
      selector:
    
        app: sc

    route(ingress).yaml
    Apisix 网关所用的 CRD(自定义资源)格式,功能同 ingress
    主要定义的资源

  • hosts 匹配的 host,网关可以根据 host 的不同分配流量到不同的服务
  • backends 负载均衡的服务,决定流量分发到哪个服务后端

    apiVersion: apisix.apache.org/v2beta2
    
    kind: ApisixRoute
    
    metadata:
    
      name: sc
    
      namespace: cs-hw
    
    spec:
    
      http:
    
        - name: sc-http
    
          match:
    
            hosts:
    
              - hw.sc.intsig.net
    
            paths:
    
              - /*
    
          backends:
    
            - serviceName: sc
    
              servicePort: 8000

    hpa.yaml
    定义容器如何扩缩容,来应对不同时间段的不同流量压力
    主要定义的资源

  • minReplicas 最小的 pod 数量
  • maxReplicas 最大的 pod 数量
  • metrics 扩容的依据,无特殊要求可以使用 K8S 本身提供的 CPU 和 Memory 监控来扩容,否则可以使用自定义方式来决定扩容方式

    apiVersion: autoscaling/v2beta1
    
    kind: HorizontalPodAutoscaler
    
    metadata:
    
      name: sc
    
    spec:
    
      scaleTargetRef:
    
        apiVersion: apps/v1
    
        kind: Deployment
    
        name: sc
    
      minReplicas: 1
    
      maxReplicas: 2
    
      metrics:
    
        - type: Resource
    
          resource:
    
            name: cpu
    
            targetAverageUtilization: 80
    
        - type: Resource
    
          resource:
    
            name: memory
    
            targetAverageUtilization: 80

    kustomization.yaml
    定义 kustomization 使用的一组资源,并且使用定义的变量替换资源中的变量,
    images 替换 deployment 中的 image 达到集中更像资源的目的

    apiVersion: kustomize.config.k8s.io/v1beta1
    
    kind: Kustomization
    
    resources:
  • deployment.yaml
  • service.yaml
  • hpa.yaml
  • route.yaml

    namespace: cs-hw

    images:

  • name: registry.intsig.net/cs_hw/sc

      newTag: e4cf9e65

    定义部署的流程
    GitLab CICD
    编写 gitlab-ci.yml
  • image CI 构建过程中使用的基础镜像,CI 过程中的所有环境基于这个镜像
  • variables CI 构建过程中所使用的变量,比如 GIT_SUBMODULE_STRATEGY 表示递归拉取gitsubmodule
  • before_script 执行 CI 之前的预处理脚本,比如定义 harbor 仓库的认证信息
  • stages CI 的步骤,主要模块,定义整个 CI 需要执行的任务
  • lint,test,build-dev 等,对应 stages 模块定义的步骤的具体实现
    Stage 的编写
  • stage Stage 的名字,可以与定义在 Stages 中的不同
  • script 此步骤执行的具体脚本,也可以定义 before_script 来执行预处理脚本
  • rules 步骤触发的规则,比如 $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" 表示当发生 merge_request 合并的 target_branch 为 develop 时触发
  • allow_failure 步骤失败时是否允许基础执行 CI
    CI 的进度
    如果没有设置 allow_failure 时,当 CI 中任一步骤失败,都将会打断 CI

    image: registry.intsig.net/cs_hw/golang:1.18-ci
    
    
    
    variables:
    
      GIT_SUBMODULE_STRATEGY: recursive
    
      DOCKER_AUTH_CONFIG: '{"auths": {"registry.intsig.net": {"auth": "cm9ib3QkY3NfaHcrY3NfaHc6MDhXbEdNTHJMc3Fuc3hKY2hoQXJKVVVXNUoxUmgxeFI="}}}'
    
    
    
    before_script:
    
      - docker login --username='robot$cs_hw+cs_hw' --password='08WlGMLrLsqnsxJchhArJUUW5J1Rh1xR' registry.intsig.net
    
    
    
    stages:
    
      - lint
    
      - test
    
      - build-dev
    
      - deploy-dev
    
      - build-prod
    
      - deploy-prod
    
    
    
    lint:
    
      stage: lint
    
      script:
    
        - make all
    
        - make lint
    
      rules:
    
        - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    
    
    
    test:
    
      stage: test
    
      script:
    
        - make all
    
        - make test
    
        - kill -2 $(pidof server.test)
    
        - sleep 4
    
        - 'cat cover.out | grep -e "/internal/" -e "mode: count" | grep -v "/data/ent/" | grep -v "internal/conf" > coverage.out'
    
        - coverage=$(go tool cover -func=coverage.out | tail -1 | grep -P '\d+\.\d+(?=\%)' -o)
    
        - echo ${coverage}
    
        - (( $(awk 'BEGIN {print ("'${coverage}'" >= "'30'")}') )) || (echo "测试覆盖率低于30%"; exit 1)
    
      artifacts:
    
        paths:
    
          - cover.out
    
      rules:
    
        - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    
    
    
    build-dev:
    
      stage: build-dev
    
      script:
    
        - make all
    
        - make dev
    
      rules:
    
        - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'
    
    
    
    build-prod:
    
      stage: build-prod
    
      script:
    
        - make all
    
        - make prod
    
      rules:
    
        - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
    
    
    
    deploy-dev:
    
      stage: deploy-dev
    
      before_script:
    
        - sleep 0.1
    
      script:
    
        - make deploy-dev
    
      rules:
    
        - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'
    
    
    
    deploy-prod:
    
      stage: deploy-prod
    
      before_script:
    
        - sleep 0.1
    
      script:
    
        - make deploy-prod
    
      rules:
    
        - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'

    如何跳过 CI
    当你的 commit message 中包含 [skip ci] 字段时,gitlab 会默认跳过这个触发的 CI,pipeline 显示为 skipped
    Go 服务的完整 CI
    golangci-lint 代码校验
    golangci-lint run --new-from-rev HEAD~4 --timeout 10m ./...
    集成测试或单元测试

    go test -c ./cmd/server/ -cover -covermode=count -coverpkg=./...
    KRATOS_CONSUL_ADDRESS=10.2.1.176:8500 KRATOS_CONSUL_TOKEN=335f912a-3403-bf1b-c127-af66e3cdd899 KRATOS_NODE_IP=127.0.0.1 ./server.test -test.coverprofile cover.out &
    sleep 10
    go test -v --count=1 ./integrationtest/service
    sleep 10
    kill -2 $(pidof server.test)
    sleep 10
    cat cover.out | grep -e "/internal/" -e "mode: count" | grep -v "/data/ent/" | grep -v "internal/conf" > coverage.out
    coverage=$(go tool cover -func=coverage.out | tail -1 | grep -P '\d+\.\d+(?=\%)' -o)
    echo ${coverage}
    (( $(awk 'BEGIN {print ("'${coverage}'" >= "'30'")}') )) || (echo "测试覆盖率低于30%"; exit 1)
    build 编译项目
    docker build -f Dockerfile --network host -t registry.intsig.net/cs_hw/sc:latest .
    deploy 部署项目
    git remote set-url origin https://gitlab_ci_hw:[email protected]/cs-hw-server/$(SERVICE).git
    git config --global user.email "[email protected]"
    git config --global user.name "GitLab CI/CD"
    git config pull.rebase false
    git checkout -b develop
    git pull origin develop
    cd deploy/dev && ls && kustomize edit set image registry.intsig.net/cs_hw/$(SERVICE):$(CI_COMMIT_SHORT_SHA)
    cat deploy/dev/kustomization.yaml
    git commit -am 'DEV image update'
    git push origin develop

    CD 自动部署
    [[ArgoCD]] 概念
    AppProject 项目
    代表应用程序逻辑分组的 Kubernetes 资源对象 Declarative Setup - Argo CD - Declarative GitOps CD for Kubernetes

  • sourceRepos 引用项目中的应用程序可以从中提取清单的存储库
  • destinations 引用项目中的应用程序可以部署到的集群和命名空间(不要使用该 name 字段,仅 server 匹配该字段)
  • roles 定义了他们对项目内资源的访问权限的实体列表
    Repo 存储库
    定义了 App 来取对应 git 存储库的密钥 Declarative Setup - Argo CD - Declarative GitOps CD for Kubernetes (repositories)
    Aplication 应用
    一个 app 代表 argocd 中最基础的单位,映射到 K8S 中的一组资源,可以为多种文件组织格式 Declarative Setup - Argo CD - Declarative GitOps CD for Kubernetes (applications)
  • K8S 原始 YAML 文件
  • kustommization 文件
  • Helm 包
    如何触发部署?
    Argocd 会定时监测对应 App 的 git 存储库文件夹的变化,当所监测的文件夹发生变动时就会触发重新部署
    `
    Argocd 操作
  • 登录
    argocd login http://argocd-test.intsig.net
  • 列出 argocd app 列表
    argocd app list
  • 列出 argocd repo 列表
    argocd repo list
  • 创建 repo
    argocd repo add https://gitlab.intsig.net/cs-hw-server/sc.git --type git --username gitlab_ci_hw --password GdfCssQTM53sLmVs --project default
  • 创建 App
    argocd create app --file=app.yaml

    定义需要部署的资源
    K8S
    Kustomization 方式部署
    deployment.yaml
    定义一组 pod 的资源,可以由多个 pod 组成容器组,不过一般不建议这么做,而是各个服务独立开来
  • image 使用的镜像 (从公司 harbor 读取)
  • env 环境变量 (consul 的地址和 token)
  • ports 对外暴露服务的端口
  • resources 资源限制 (hpa 扩容的依据)
  • readinessProbe,livenessProbe 就绪探针和存活探针(K8S 重启服务和滚动更新的依据)
    就绪探针和存活探针
    就绪探针:K8S 会定时的访问提供的端口(TCP)或 URI(HTTP)确保服务以及就绪,将就绪的服务加入到负载均衡,提供外部或其他服务访问
    存活探针:K8S 会定时的访问提供的端口(TCP)或 URI(HTTP)确保服务以及就绪,将非存活的服务踢出负载均衡

    apiVersion: apps/v1

kind: Deployment

metadata:

  name: sc

  namespace: cs-hw

spec:

  replicas: 1

  selector:

    matchLabels:

      app: sc

  template:

    metadata:

      labels:

        app: sc

    spec:

      containers:

        - name: sc

          image: registry.intsig.net/cs_hw/sc:latest

          imagePullPolicy: Always

          env:

            - name: KRATOS_CONSUL_ADDRESS

              value: 10.2.1.176:8500

            - name: KRATOS_CONSUL_TOKEN

              value: 335f912a-3403-bf1b-c127-af66e3cdd899

            - name: KRATOS_NODE_IP

              valueFrom:

                fieldRef:

                  fieldPath: status.hostIP

          ports:

            - containerPort: 8000

            - containerPort: 9000

          resources:

            limits:

              cpu: "500m"

              memory: "1Gi"

          livenessProbe:

            tcpSocket:

              port: 9000

          readinessProbe:

            tcpSocket:

              port: 9000

      restartPolicy: Always

service.yaml
定义对外暴露服务的方式
主要定义的资源
- 服务类型
- port 暴露的端口,选项 targetPort (容器端口)不填默认为 port
- selector 选择服务对应的 deployment

apiVersion: v1

kind: Service

metadata:

  name: sc

  namespace: cs-hw

spec:

  type: ClusterIP

  ports:

    - port: 8000

      name: http

    - port: 9000

      name: grpc

  selector:

    app: sc

route(ingress).yaml
Apisix 网关所用的 CRD(自定义资源)格式,功能同 ingress
主要定义的资源
- hosts 匹配的 host,网关可以根据 host 的不同分配流量到不同的服务
- backends 负载均衡的服务,决定流量分发到哪个服务后端

apiVersion: apisix.apache.org/v2beta2

kind: ApisixRoute

metadata:

  name: sc

  namespace: cs-hw

spec:

  http:

    - name: sc-http

      match:

        hosts:

          - hw.sc.intsig.net

        paths:

          - /*

      backends:

        - serviceName: sc

          servicePort: 8000

hpa.yaml
定义容器如何扩缩容,来应对不同时间段的不同流量压力
主要定义的资源
- minReplicas 最小的 pod 数量
- maxReplicas 最大的 pod 数量
- metrics 扩容的依据,无特殊要求可以使用 K8S 本身提供的 CPU 和 Memory 监控来扩容,否则可以使用自定义方式来决定扩容方式

apiVersion: autoscaling/v2beta1

kind: HorizontalPodAutoscaler

metadata:

  name: sc

spec:

  scaleTargetRef:

    apiVersion: apps/v1

    kind: Deployment

    name: sc

  minReplicas: 1

  maxReplicas: 2

  metrics:

    - type: Resource

      resource:

        name: cpu

        targetAverageUtilization: 80

    - type: Resource

      resource:

        name: memory

        targetAverageUtilization: 80

kustomization.yaml
定义 kustomization 使用的一组资源,并且使用定义的变量替换资源中的变量,
images 替换 deployment 中的 image 达到集中更像资源的目的

apiVersion: kustomize.config.k8s.io/v1beta1

kind: Kustomization

resources:

  • deployment.yaml
  • service.yaml
  • hpa.yaml
  • route.yaml

namespace: cs-hw

images:

  • name: registry.intsig.net/cs_hw/sc

  newTag: e4cf9e65

定义部署的流程
GitLab CICD
编写 gitlab-ci.yml
主要步骤
- image CI 构建过程中使用的基础镜像,CI 过程中的所有环境基于这个镜像
- variables CI 构建过程中所使用的变量,比如 GIT_SUBMODULE_STRATEGY 表示递归拉取gitsubmodule
- before_script 执行 CI 之前的预处理脚本,比如定义 harbor 仓库的认证信息
- stages CI 的步骤,主要模块,定义整个 CI 需要执行的任务
- lint,test,build-dev 等,对应 stages 模块定义的步骤的具体实现
Stage 的编写
- stage Stage 的名字,可以与定义在 Stages 中的不同
- script 此步骤执行的具体脚本,也可以定义 before_script 来执行预处理脚本
- rules 步骤触发的规则,比如 $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" 表示当发生 merge_request 合并的 target_branch 为 develop 时触发
- allow_failure 步骤失败时是否允许基础执行 CI
CI 的进度
如果没有设置 allow_failure 时,当 CI 中任一步骤失败,都将会打断 CI

image: registry.intsig.net/cs_hw/golang:1.18-ci

variables:

  GIT_SUBMODULE_STRATEGY: recursive

  DOCKER_AUTH_CONFIG: '{"auths": {"registry.intsig.net": {"auth": "cm9ib3QkY3NfaHcrY3NfaHc6MDhXbEdNTHJMc3Fuc3hKY2hoQXJKVVVXNUoxUmgxeFI="}}}'

before_script:

  - docker login --username='robot$cs_hw+cs_hw' --password='08WlGMLrLsqnsxJchhArJUUW5J1Rh1xR' registry.intsig.net

stages:

  - lint

  - test

  - build-dev

  - deploy-dev

  - build-prod

  - deploy-prod

lint:

  stage: lint

  script:

    - make all

    - make lint

  rules:

    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

test:

  stage: test

  script:

    - make all

    - make test

    - kill -2 $(pidof server.test)

    - sleep 4

    - 'cat cover.out | grep -e "/internal/" -e "mode: count" | grep -v "/data/ent/" | grep -v "internal/conf" > coverage.out'

    - coverage=$(go tool cover -func=coverage.out | tail -1 | grep -P '\d+.\d+(?=\%)' -o)

    - echo ${coverage}

    - (( $(awk 'BEGIN {print ("'${coverage}'" >= "'30'")}') )) || (echo "测试覆盖率低于30%"; exit 1)

  artifacts:

    paths:

      - cover.out

  rules:

    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

build-dev:

  stage: build-dev

  script:

    - make all

    - make dev

  rules:

    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'

build-prod:

  stage: build-prod

  script:

    - make all

    - make prod

  rules:

    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'

deploy-dev:

  stage: deploy-dev

  before_script:

    - sleep 0.1

  script:

    - make deploy-dev

  rules:

    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'

deploy-prod:

  stage: deploy-prod

  before_script:

    - sleep 0.1

  script:

    - make deploy-prod

  rules:

    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'

如何跳过 CI
当你的 commit message 中包含 [skip ci] 字段时,gitlab 会默认跳过这个触发的 CI,pipeline 显示为 skipped
Go 服务的完整 CI
golangci-lint 代码校验
golangci-lint run --new-from-rev HEAD~4 --timeout 10m ./...
集成测试或单元测试
go test -c ./cmd/server/ -cover -covermode=count -coverpkg=./...
KRATOS_CONSUL_ADDRESS=10.2.1.176:8500 KRATOS_CONSUL_TOKEN=335f912a-3403-bf1b-c127-af66e3cdd899 KRATOS_NODE_IP=127.0.0.1 ./server.test -test.coverprofile cover.out &
sleep 10
go test -v --count=1 ./integrationtest/service
sleep 10
kill -2 $(pidof server.test)
sleep 10
cat cover.out | grep -e "/internal/" -e "mode: count" | grep -v "/data/ent/" | grep -v "internal/conf" > coverage.out
coverage=$(go tool cover -func=coverage.out | tail -1 | grep -P '\d+\.\d+(?=\%)' -o)
echo ${coverage}
(( $(awk 'BEGIN {print ("'${coverage}'" >= "'30'")}') )) || (echo "测试覆盖率低于30%"; exit 1)
build 编译项目
docker build -f Dockerfile --network host -t registry.intsig.net/cs_hw/sc:latest .
deploy 部署项目
git remote set-url origin https://gitlab_ci_hw:[email protected]/cs-hw-server/$(SERVICE).git
git config --global user.email "[email protected]"
git config --global user.name "GitLab CI/CD"
git config pull.rebase false
git checkout -b develop
git pull origin develop
cd deploy/dev && ls && kustomize edit set image registry.intsig.net/cs_hw/$(SERVICE):$(CI_COMMIT_SHORT_SHA)
cat deploy/dev/kustomization.yaml
git commit -am 'DEV image update'
git push origin develop
CD 自动部署
[[ArgoCD]] 概念
AppProject 项目
代表应用程序逻辑分组的 Kubernetes 资源对象 Declarative Setup - Argo CD - Declarative GitOps CD for Kubernetes
- sourceRepos 引用项目中的应用程序可以从中提取清单的存储库
- destinations 引用项目中的应用程序可以部署到的集群和命名空间(不要使用该 name 字段,仅 server 匹配该字段)
- roles 定义了他们对项目内资源的访问权限的实体列表
Repo 存储库
定义了 App 来取对应 git 存储库的密钥 Declarative Setup - Argo CD - Declarative GitOps CD for Kubernetes (repositories)
Aplication 应用
一个 app 代表 argocd 中最基础的单位,映射到 K8S 中的一组资源,可以为多种文件组织格式 Declarative Setup - Argo CD - Declarative GitOps CD for Kubernetes (applications)
- K8S 原始 YAML 文件
- kustommization 文件
- Helm 包
如何触发部署?
Argocd 会定时监测对应 App 的 git 存储库文件夹的变化,当所监测的文件夹发生变动时就会触发重新部署
`
Argocd 操作
- 登录
argocd login http://argocd-test.intsig.net
- 列出 argocd app 列表
argocd app list
- 列出 argocd repo 列表
argocd repo list
- 创建 repo
argocd repo add https://gitlab.intsig.net/cs-hw-server/sc.git --type git --username gitlab_ci_hw --password GdfCssQTM53sLmVs --project default
- 创建 App
argocd create app --file=app.yaml

你可能感兴趣的:(https)