一、kubernetes
DevOps和无运维
抽象了数据中心的硬件基础设施,使得对外暴露的只是一个巨大的资源池,不用关注底层服务器。简化了应用的开发、部署,以及对开发和运维团队的管理。
- Kubernetes使开发者可以自主部署应用,并且控制部署的频率,完全脱离运维团队的帮助;(NoOps)
- Kubernetes同时能让运维团队监控整个系统,并且在硬件故障时重新调度应用

1.1 容器
容器的本质就是进程
- Linux命名空间
- 文件、进程、网络接口、主机名等
- Linux控制组(cgroups)
- 进程能使用的资源量(CPU、内存、网络宽带等)
创建进程后,先使用namespace技术进行资源隔离,然后再利用CGroups技术为容器创建资源限制的配置文件
1.2 Pod
核心概念,其它的对象都是在管理、暴露pod或者被pod使用
为何需要Pod?为何不直接使用使用容器?为何甚至同时需要运行多个容器

在kubernetes中,容器就相当于是一个进程(Linux线程),Pod就是进程组(Linux线程组)。

Pod,实际上是在扮演传统基础设施里“虚拟机”的角色;而容器,则是这个虚拟机里运行的用户程序。
凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的。这些属性的共同特征是,它们描述的是“机器”这个整体,而不是里面运行的“程序”
- “机器”的网卡
- “机器”的磁盘
- “机器”的防火墙
- “机器”运行在哪个服务器之上
YAML描述文件

三大重要组成部分
- metadata 包括名称、命名空间、标签和关于该容器的其它信息
- spec 包含pod内容的实际说明,例如容器、卷和其它信息
- status 包含运行中的pod的当前信息,例如pod所处的条件、每个容器的描述和状态,以及内部IP和其它基本信息
标签的用途是标识和分组对象,而注解用于提供对象来源、如何使用及其策略的额外信息
1.3 servcie
-
为什么需要服务
- Pod的IP不是固定的
- 一组Pod实例的负载均衡
解决不断变化的pod IP地址的问题 当一个服务被创建时,它会得到一个静态的IP,在服务的生命周期中这个IP不会发生改变。客户端应该通过固定IP地址连接到服务,而不是直接连接pod。服务会确保其中一个pod接收连接,而不关心pod当前运行在哪里(以及它的IP地址是什么) 对外暴露一系列pod、稳定的IP地址以及端口
-
服务是如何实现的(使用场景)
- clusterIP

kube-dns生成的 DNS记录格式: [serviceName].[namespace].svc.cluster.local
- NodePort


- Headless Service
Headless 的作用就是绕过 Cluster IP 提供的负载均衡,由自己决定要访问哪个 Pod。 配了 Headless 后除了可以使用 IP 访问 Pod,还可以使用域名 [podName].[serviceName].[namespace].svc.cluster.local
默认NIFI节点: nifi-0.nifi-headless.gdc.svc.cluster.local:8080
- ExternalName
把集群外部的服务引入到集群内部来,在集群内部直接使用。

apiVersion: v1
kind: Service
metadata:
name: gdc-assets-iot-service
namespace: middleware
spec:
type: ExternalName
externalName: gdc-assets-iot-service.gdc.svc.cluster.local
1.4 ingress
就是 Service 的“Service”。
k8s可以通过三种方式将集群内服务暴露到外网
- NodePort
- LoadBalancer
- Ingress
为什么需要Ingress
- Ingress在HTTP应用层操作,可以提供一些服务不能实现的功能,可以根据 http header, path 进行路由转发
- Ingress 实际上就是 Kubernetes 对“反向代理”的抽象

1.5 控制器/编排(工作负载)
- Deployment(无状态应用)


YMAL描述

- StatefulSet (有状态应用)
- DaemonSet(守护进程)
- Job(离线业务)
二、Helm
2.1 简介
核心思想:所有k8s资源对象都可以打包在一起进行安装、更新和删除。
可以将Helm看作Kubernetes下的apt-get/yum
官方文档:v3.helm.sh/zh/docs/

Helm Client 是一个命令行下的客户端工具。主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建和管理本地和远程的 Chart 仓库。
三个重要的概念
Chart: 代表一个 Helm 包。它包含了在 Kubernetes 集群中运行应用程序、工具或服务所需的所有 YAML 格式的资源定义文件。Repository(仓库): 它是用来存放和共享 Helm Chart 的地方,类似于存放源码的 GitHub 的 Repository,以及存放镜像的 Docker 的 Repository。Release:它是运行在 Kubernetes 集群中的 Chart 的实例。一个 Chart 通常可以在同一个集群中安装多次。每一次安装都会创建一个新的 Release。 每个 Release 包含多个 Kubernetes 资源,例如 Deployment、Pod、Service 等。
2.2 为什么要使用 Helm
- 传统的应用部署模式

每个服务由一个复杂的 Kubernetes YAML 格式的文件来定义并创建,可以看到如果靠传统的方式,去维护这些 YAML 格式文件,并在不同环境下使用不同的配置去创建应用,是一件非常复杂的工作
- 我们需要一种更好的方式,来维护和管理这些 YAML 文件

Helm 的模板文件基于text/template模板文件,提供了更加强大的模板渲染能力。Helm 可以将配置文件中的值渲染进模板文件中,最终生成一个可以部署的 Kubernetes YAML 格式的资源定义文件
- 部署一个应用可以简化为Chart模板(多个服务) + Chart配置 -> 应用

Chart 模板一个应用只用编写一次,可以重复使用。在部署时,可以指定不同的配置,从而将应用部署在不同的环境中,或者在同一环境中部署不同配置的应用。
- 查看release在k8s中创建出来的资源
- helm get manifest catalog-server-service -n gdc

2.3 Chart包
| 文件 | 含义 |
|---|---|
| charts | 一个普通的空文件 |
| Chart.yaml | 当前 chart 属性的配置信息 |
templates | 自己定义的 yaml 文件存于此 |
values.yaml | 定义 yaml 文件的全局配置 |
主要包含两类文件
- n个模板文件
- 1个配置文件
2.3.1 中间件包

2.3.2 GDC通用包

未解决问题:range作用域内读取外部配置
2.3.3 配置说明
三、SQL管理规范
文件存放目录及文件命名规范
sql语句规范
- postgresql
- mysql
四、jenkins流水线
3.1 运行系统
运行系统概述

项目类型
- 自由风格类型项目
- 流水线项目
3.2 pipeline
Pipeline 是Jenkins 2.X 的最核心的特性。让jenkins 可以实现持续交付管道的落地和实施
- Jenkins 1.x只能通过界面手动配置来配置描述过程,部署流水线完成任务
- Jenkins 2.x支持pipeline as code,可以通过代码来描述部署流水线
可以像管理其它源代码一样通过文件的形式来管理Jenkins任务,支持历史追溯、差异对比等。 更好的版本化、协作、重用
3.2.1 语法(Jenkinsfile)
基于Groovy语言实现的一种DSL(领域特定语言)。流水线通过Jenkins DSL编写代码来实现
git branch:'CIM_v2.4.5',url:'https://geek.******.com/scm/gdcc/gdc-install.git'
#
- 声明式
-
pipeline : 代表整条流水线,包含整条流水线的逻辑。
-
agent :节点,指定流水线的执行位置
-
stages :阶段集,流水线中多个stage的容器
-
stage : 阶段,代表流水线的阶段
-
steps :步骤,代表阶段中的一个或多个具体步骤的容器
-
post :构建后的操作
-
parameters :参数
-
triggers :触发器
-

- 部分:stages、steps、posts (有点容器的意思,隔离)
- 指令:是一个做任何一下事情的语句或代码块
- 定义值 agent
- 配置行为 triggers
- 指定要完成的行为 state
- 步骤:steps部分内部语句
- 条件:when、conditions
- 优点
- 更结构化,贴近传统的Jenkins Web表单形式
- 更强大的声明内容能力,高可读性
- 可以通过Bule Ocean图形化界面自动生成
- 段落可映射到常见的Jenkins概念,比如通知
- 更友好的语法检查和错误识别
- 提升流水线间的一致性
- 缺点
- 对迭代逻辑支持较弱(相比程序而言)
- 仍在开发完善中(对于传统Jenkins中的部分功能缺乏支持)
- 更严格的结构(更难实现自定义流水线代码)
- 目前对于复杂的流水线和工作流难以胜任
- 脚本式
- 优点
- 更少的代码段落和若规范要求
- 更强大的程序代码能力
- 更像编写代码程序
- 传统的流水线即代码模型,用户熟悉并向后兼容性
- 更灵活的自定义代码操作
- 能够构建更复杂的工作流和流水线
- 缺点
- 普遍要求更好的编程水平
- 语法检查受限于Groovy语言及环境
- 和传统的Jenkins模型有很大的差异
- 与声明式流水线的实现相比,同一工作流会更复杂
3.2.2 实现
- Pipeline Script
- Pipeline script from SCM
流水线脚本默认名字【Jenkinsfile】
脚本实现

pipeline {
agent {
kubernetes {
inheritFrom "jenkins-slave"
yaml '''
apiVersion: v1
kind: Pod
metadata:
name: jenkins-slave
spec:
containers:
- name: jnlp
image: *****-registry.cn-beijing.cr.aliyuncs.com/gdc/pipelinedata:v3
imagePullPolicy: Always
env:
- name: "MYSQLHOST"
value:
- name: "MYSQLUSER"
value: root
- name: "MYSQLPWD"
value: ******
- name: "MYSQLPORT"
value: 3306
.....
- name: "MQTT_HOST"
value: 10.9.31.99
- name: "MQTT_PORT"
value: 1883
volumeMounts:
- mountPath: /root/.kube
name: config-volume
- mountPath: /home/release
name: release-shared-db
imagePullSecrets:
- name: ******-aliyun-docker
volumes:
- configMap:
name: ops-xa-te-kube
name: config-volume
- name: release-shared-db
persistentVolumeClaim:
claimName: release-shared-db
'''
}
}
// triggers{
// cron('H 02 * * *')
// }
options{
//Disallow concurrent executions of the Pipeline. Can be useful for preventing simultaneous accesses to shared resources, etc.
disableConcurrentBuilds()
}
environment {
CREDENTIALSID = "shiyw-a"
GITURL="https://geek.******.com/scm/gdcc/gdc-install.git"
GITBRANCH="CIM_v2.4.20"
}
stages {
stage('pull sql and script') {
steps {
container(name: 'jnlp'){
dir('/home/release/gdc-install'){
deleteDir()
git branch:env.GITBRANCH,credentialsId:env.CREDENTIALSID,url:env.GITURL
}
}
}
}
stage('uninstall gdc') {
steps {
container(name: 'jnlp'){
sh 'helm uninstall service-market-web -n ${NAMESPACE} || true'
sh 'helm uninstall service-market-server -n ${NAMESPACE} || true'
......
sh 'sleep 1s'
sh 'helm list -n ${NAMESPACE}'
}
}
}
stage('uninstall middleware') {
steps {
container(name: 'jnlp'){
sh 'helm uninstall grafana -n ${NAMESPACE} || true'
sh 'helm uninstall prometheus -n ${NAMESPACE} || true'
sh 'helm uninstall elasticsearch -n ${NAMESPACE} || true'
sh 'helm uninstall nifi -n ${NAMESPACE} || true'
sh 'helm uninstall nifi-standalone -n ${NAMESPACE} || true'
sh 'helm uninstall dolphinscheduler3 -n ${NAMESPACE} || true'
sh 'helm uninstall minio -n ${NAMESPACE} || true'
sh 'helm uninstall zookeeper -n ${NAMESPACE} || true'
sh 'helm uninstall apollo-service -n ${NAMESPACE} || true'
sh 'helm uninstall apollo-portal -n ${NAMESPACE} || true'
sh 'helm uninstall emqx -n ${NAMESPACE} || true'
sh 'sleep 1s'
sh 'helm list -n ${NAMESPACE}'
// 批量清除gdc命名空间下的所有helm test
sh 'helm list -n ${NAMESPACE} | awk \'{print $1}\' | grep -v NAME |xargs -I {} helm uninstall {} -n ${NAMESPACE} || true'
// 批量清除gdc命名空间下的所有pvc
sh 'kubectl get pvc -n ${NAMESPACE} | awk \'{print $1}\' | grep -v NAME |xargs kubectl delete pvc -n ${NAMESPACE} || true'
}
}
}
stage('clean data') {
steps {
container(name: 'jnlp'){
sh """
cd /root/clean_data
pwd
echo "$TDENGINEHOST $TDENGINEHOSTNAME" >> /etc/hosts
cd TDengine-client-3.0.6.0
./install_client.sh
cd /root/clean_data
bash delete_orientdb.sh
sh delete_kafka.sh || true
# redis-cli -h ${REDISHOST} -p ${REDISPORT} -a ${REDISPASSWORD} flushall
# sleep 30s
cat /var/log/clean.log
"""
dir('/home/release/gdc-install/tool'){
sh 'bash delete_tdengine.sh'
}
// sh 'redis-cli -h ${REDISHOST} -p ${REDISPORT} -a ${REDISPASSWORD} flushall'
sh 'redis-cli -h ${REDISHOST} -p ${REDISPORT} -a ${REDISPASSWORD} -n 0 flushdb'
sh 'redis-cli -h ${REDISHOST} -p ${REDISPORT} -a ${REDISPASSWORD} -n 1 flushdb'
sh 'redis-cli -h ${REDISHOST} -p ${REDISPORT} -a ${REDISPASSWORD} -n 2 flushdb'
sh 'psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname=\'kong\' AND pid<>pg_backend_pid();"'
sh 'dropdb -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} "kong" || true'
......
sh 'psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname=\'dolphinscheduler\' AND pid<>pg_backend_pid();"'
sh 'dropdb -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} "dolphinscheduler" || true'
sh 'mysql -h${MYSQLHOST} -u${MYSQLUSER} -p${MYSQLPWD} -e "DROP DATABASE IF EXISTS apollo_config"'
......
}
}
}
stage('initialize data') {
steps {
container(name: 'jnlp'){
dir('/home/release/gdc-install/sql/all'){
sh 'mysql -h${MYSQLHOST} -u${MYSQLUSER} -p${MYSQLPWD} < middleware/apollo/apollo_config__mysql_ddl.sql'
sh 'mysql -h${MYSQLHOST} -u${MYSQLUSER} -p${MYSQLPWD} < middleware/apollo/apollo_config__mysql_dml.sql'
......
}
}
}
}
stage('install middleware') {
steps {
container(name: 'jnlp'){
sh 'cd /home/release/gdc-install/helm/installCommand/0-secret && sh digitalcity-aliyun-docker.sh || true'
sh 'chmod +x /home/release/gdc-install/helm/installCommand/1-middleware'
sh 'cd /home/release/gdc-install/helm/installCommand/1-middleware && sh 1-helm-apollo-service.sh'
sh 'cd /home/release/gdc-install/helm/installCommand/1-middleware && sh 2-helm-apollo-portal.sh'
sh 'cd /home/release/gdc-install/helm/installCommand/5-check && bash gdc-pod-status-check.sh apollo-service Running'
sh 'cd /home/release/gdc-install/helm/installCommand/5-check && bash gdc-pod-status-check.sh apollo-portal Running'
sh 'sleep 2m'
sh 'cd /home/release/gdc-install/helm/installCommand/4-gdc && sh gdc-apollo-init-job.sh'
sh 'cd /home/release/gdc-install/helm/installCommand/1-middleware && sh 3-helm-zookeeper.sh'
sh """
cd /home/release/gdc-install/helm/installCommand/5-check
bash gdc-pod-status-check.sh zookeeper Running
"""
dir('/home/release/gdc-install/helm/installCommand/1-middleware'){
sh 'sh 4-helm-minio.sh'
sh 'sh 5-helm-dolphin.sh'
sh 'sh 6-helm-nifi.sh'
}
sh """
cd /home/release/gdc-install/helm/installCommand/5-check
bash gdc-pod-status-check.sh nifi Running
"""
dir('/home/release/gdc-install/helm/installCommand/1-middleware'){
sh 'sh 9-helm-elasticsearch.sh'
// sh 'sh 10-helm-prometheus.sh'
// sh 'sh 11-helm-grafana.sh'
}
sh 'cd /home/release/gdc-install/helm/installCommand/2-config && sh helm-kong-config.sh'
dir('/home/release/gdc-install/helm/installCommand/4-gdc'){
sh 'sh kong-cp.sh'
sh 'sleep 30s'
sh 'sh kong-dp.sh'
}
dir('/home/release/gdc-install/helm/installCommand/1-middleware'){
sh 'sh 12-helm-emqx.sh'
}
sh 'helm list -n ${NAMESPACE}'
}
}
}
stage('check middleware pod status') {
steps {
container(name: 'jnlp'){
sh 'cd /home/release/gdc-install/helm/installCommand/5-check && bash gdc-pod-all-check.sh'
}
}
}
stage('install gdc') {
steps {
container(name: 'jnlp'){
sh 'chmod +x /home/release/gdc-install/helm/installCommand/2-config'
sh 'chmod +x /home/release/gdc-install/helm/installCommand/3-pvc'
sh 'chmod +x /home/release/gdc-install/helm/installCommand/4-gdc'
sh 'cd /home/release/gdc-install/helm/installCommand/2-config && sh helm-cim-web-config.sh'
sh 'cd /home/release/gdc-install/helm/installCommand/2-config && sh helm-gdc-common.sh'
sh 'cd /home/release/gdc-install/helm/installCommand/3-pvc && sh helm-object-services.sh'
dir('/home/release/gdc-install/helm/installCommand/4-gdc'){
sh 'sh platform-foundation.sh'
sh 'sh platform-api-definition.sh'
......
}
sh 'sleep 2s'
sh 'helm list -n ${NAMESPACE}'
}
}
}
stage('check all pod status') {
steps {
container(name: 'jnlp'){
sh 'cd /home/release/gdc-install/helm/installCommand/5-check && bash gdc-pod-all-check.sh 30'
}
}
}
stage('metersphere') {
steps{
script {
meterSphere method: 'testPlan',
mode: 'serial',
msAccessKey: '3XlCrXrJZB52PBpT',
msEndpoint: 'http://10.0.68.20:31259/',
msSecretKey: 'K9TTRaQslcJqzN03',
openMode: 'auth',
projectId: '10950575-6ee8-46cb-9362-2ecbefede248',
rojectName: '',
projectType: 'projectId',
resourcePoolId: '',
testCaseId: '',
testCaseName: '',
testPlanId: 'd40f4dc1-5e40-402a-95c2-fb6cd4a8cc6d',
testPlanName: '',
workspaceId: '19740116-bf0a-11ed-ac16-fa163e3ecbeb'
}
}
}
}
}
3.2.3 多分支流水线
- Jenkinsfile 在项目的根目录
- 配置扫描 多分支流水线 触发器 ,扫描策略,若发现变化,就执行Jenkinsfile的脚本内容,若无变化就不执行;也可手动执行

