定义需要部署的资源
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 中任一步骤失败,都将会打断 CIimage: 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