维护说明
# 维护说明
# 文件更新说明
# K8s简介
# 为什么要有k8s,使用它有什么好处
在传统的分布式系统解决方案中,需要很多人(其中不缺乏技术达人)一起分工协作才能设计、实施和运维分布式系统, 采用 k8s 解决方案后,只需一个精悍的小团队就能轻松应付。这个精悍的小团只需一名架构师负责系统服务组件的架构设 计,几名开发工程师负责业务代码的开发,一名系统兼运维工程师负责 k8s 的部署和运维即可。
2015 年,谷歌联合 20 多家公司一起建立了 CNCF(Cloud Native Computing Foundation,云原生计算基金会)开源组织 来推广 k8s,它是基于容器的大规模容器化分布式系统解决方案,得到以谷歌为首的 IT 巨头们的大力宣传和持续推进。 如今,数百家厂商和技术社区共同构建了非常强大的云原生生态。
优点:- 控制和管理应用程序对资源的使用;
- 自动负载均衡应用程序的多个实例之间请求;
- 监控资源使用和资源限制,为了可以自动阻止应用消耗过多的资源并且可以再次恢复它们;
- 如果主机资源耗尽或死机,将应用程序实例从一台主机迁移到另一台主机;
- 当有新的主机加入集群时,新增加的额外资源可以被自动使用。
# K8s定义
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。
Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。
# K8s组成
架构图如下:
# Master 节点
详情
- API Server
I.整个集群管理的 API 接口:所有对集群进行的查询和管理都要通过 API 来进行。集群内部的组件(如 kubelet)也 是通过 Apiserver 更新和同步数据到 etcd 中。
II.集群内部各个模块之间通信的枢纽:所有模块之前并不会之间互相调用,而是通过和 API Server 打交道来完成 自己那部分的工作。
III.集群安全控制:API Server 提供的验证和授权保证了整个集群的安全。
IV.数据中心枢纽: API Server 负责和 Etcd 交互存放集群用到的运行数据。
- Scheduler 负责对集群内部的资源进行调度,相当于“调度室”
负责节点资源管理,接收来自 kube-apiserver 创建 Pods 的任务,收到任务后它会检索出所有符合该 Pod 要求的 Node 节点(通过预选策略和优选策略),开始执行 Pod 调度逻辑。调度成功后将 Pod 绑定到目标节点上。
- Controller manager
controller-manager 作为 k8s 集群的管理控制中心,负责集群内 Node、Namespace、Service、Token、Replication等资源对象的管理,使集群内的资源对象维持在预期的工作状态。 每一个 controller 通过 api-server 提供的 restful 接口实时监控集群内每个资源对象的状态,当发生故障,导致资 源对象的工作状态发生变化,就进行干预,尝试将资源对象从当前状态恢复为预期的工作状态,常见的 controller 有 Namespace Controller、Node Controller、Service Controller、ServiceAccount Controller、Token Controller、ResourceQuote Controller、Replication Controller 等。
- Etcd
etcd 在 kubernetes 集群是用来存放数据并通知变动的。 Kubernetes 中没有用到数据库,它把关键数据都存放在 etcd 中,这使 kubernetes 的整体结构变得非常简单。在 kubernetes 中,数据是随时发生变化的,比如说用户提交了新任务、增加了新的 Node、Node 宕机了、容器死掉了等等,都会触发状态数据的变更。状态数据变更之后呢,Master 上的 kube-scheduler 和 kube-controller-manager,就会重新安排 工作,它们的工作安排结果也是数据。这些变化,都需要及时地通知给每一个组件。etcd 有一个特别好用的特性,可以调用它的 api 监听其中的数据,一旦数据发生变化了,就会收到通知。有了这个特性之后,kubernetes 中的每个组件只需要监听 etcd 中数据,就可以知道自己应该做什么。kube-scheduler 和 kube-controller-manager 呢,也只需要把最新的工作安排写入到 etcd 中就可以了,不用自己费心去逐个通知了。
# Node 节点
详情
- Pod
Pod 是 Kubernetes 最基本的操作单元。一个 Pod 代表着集群中运行的一个进程,它内部封装了一个或多个紧密相关的容器。
- Kubelet
运行在每个计算节点上 I.kubelet 组件通过 api-server 提供的接口监测到 kube-scheduler 产生的 pod 绑定事件,然后从 etcd 获取 pod 清单,下载镜像并启动容器。 II.同时监视分配给该 Node 节点的 pods,周期性获取容器状态,再通过 api-server 通知各个组件。
- kube-proxy
首先 k8s 里所有资源都存在 etcd 中,各个组件通过 apiserver 的接口进行访问 etcd 来获取资源信息。kube-proxy 会作为 daemon(守护进程) 跑在每个节点上通过 watch 的方式监控着 etcd 中关于 Pod 的最新状态信息,它一旦检查到一个 Pod 资源被删除了或新建或 ip 变化了等一系列变动,它就立即将这些变动,反应在 iptables 或 ipvs 规则中,以便之后再有请求发到 service 时,service 可以通过 ipvs 最新的规则将请求的分发到 pod 上。
# 网络存储卷、NFS、PV、PVC简介
K8s中的Pod是有自愈能力的,一个Pod内的容器是有可能被重新启动的(如果出现了异常)。在Docker中我们学到过,容器内的数据都是临时存储的,当容器被重启或删除,它里面的数据也会被删除,因此数据的持久化就是非常必要的了。 K8s是分布式容器集群,如何在多个Pod之间或多个Node之间进行数据存储和共享是非常重要的问题。K8s引入了网络存储卷,它支持为数众多的云提供商的产品和网络存储方案。网络存储卷还能够满足持久化数据的要求,这些数据将永久保存。网络存储卷是集成各种第三方的存储系统,不同的服务商提供的配置有一些不同,NFS只是其中一种。 简单来说,存储卷是定义在Pod资源之上、可被其内部的所有容器挂载的共享目录,它关联至某外部的存储设备之上的存储空间,从而独立于容器自身的文件系统,而数据是否具有持久能力取决于存储卷自身是否支持持久机制。 在 Docker中 ,想要持久化使用数据,需要把主机上的目录挂载到 Docker 中去。K8s 数据卷是 docker 数据卷的扩展,K8s 可以适配各种存储系统,如:EmptyDir,HostPath, 网络存储(NFS,GlusterFS,PV/PVC)等。我们这里采用 NFS + PV/PVC 网络存储方案实现我们的 K8s 数据持久化。 NFS 是 Network File System 的简写,即网络文件系统。NFS 基于 RPC (Remote Procedure Call) 远程过程调用实现,其允许一个系统在网络上与它人共享目录和文件。通过使用 NFS,用户和程序就可以像访问本地文件一样访问远端系统上的文件。并且NFS是一个持久化卷,如果删除一个Pod,而下一个Pod使用了指向主机上相同路径的NFS卷,则新Pod将会发现上一个Pod留下的数据。
我们发现所有的持久卷类型都要求Pod的开发人员了解集群中可用的真实网络存储的基础结构。例如,要创建支持NFS协议的卷,开发人员必须知道NFS节点所在的实际服务器。而K8s的理念是向应用程序及其开发人员隐藏真实的基础设施,使他们不必担心基础设施的具体状态。比如,开发人员要部署的应用程序到底部署在哪个节点上他根本不用关心,直接交给K8s就行了。 所以,理想情况下是,在K8s上部署应用程序的开发人员不需要知道底层使用的技术细节(应用程序部署在哪台机器、存储技术等)。这些是交给集群管理员去考虑的。开发人员需要一定数量的持久化存储为应用持久化数据时,只需要向K8s申请就行了,PV和PVC的概念就诞生了!就像在创建Pod时可以请求CPU、内存和其他机器资源一样,集群管理员可以对集群进行配置,让其可以为应用程序提供所需的服务。
PV 的全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象,PV 由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,是通过插件机制完成与共享存储(比如NFS)的对接。 PVC 的全称是:PersistentVolumeClaim(持久化卷声明),PVC 是用户存储的一种声明,通常由普通用户创建和维护。需要为 Pod 分配存储资源时,用户可以创建一个 PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,K8s 会查找并提供满足条件的 PV。 简而言之,PV是集群中的资源,PVC是对这些资源的请求,也是对资源的索赔检查。
# 映射路径
详情
在deployment-yaml文件里面定义了K8s容器内部目录与nfs服务器映射目录(宿主机目录)的一一对应关系。
K8s一键部署后会自动生成容器内映射目录和nfs服务器映射目录。 nfs服务器映射路径为/var/hicampusdata/gwiotcenter。
在k8s环境中,容器的/opt/ganwei/IoTCenter/dllToCopy/目录是被映射进去的,对容器进行删除和更新操作,这个目录中的文件不会受到影响。
# 更新原理
详情
一层映射:宿主机目录dllToCopy和容器内目录dllToCopy存在映射关系。 二层映射:容器的runGW.sh文件写入了脚本,容器启动的时候会自动执行该脚本,把容器中dllToCopy目录下的文件拷贝覆盖到IoTCenter目录下对应的文件夹中。
假如我们想更新容器内IoTCenter/dll目录中的动态库文件。需要在宿主机dllToCopy文件夹里面新建一个dll文件夹,把需要更新的动态库拷贝到dllToCopy/dll文件夹里,之后重启容器,就可以将文件更新到IoTCenter/dll目录中。 映射流程如下: 宿主机dllToCopy/dll --> 容器内dllToCopy/dll --> IoTCenter/dll 如果想更新其它的文件也是这样做,比如更新wwwroot目录下的文件。在宿主机dllToCopy目录下新建这样一个路径/IoTCenterWeb/publish/wwwroot/,把要更新的文件放在新建的wwwroot中,重启容器就可以完成更新了。
注意
如果出现因权限问题映射失败的问题,需要在宿主机目录dllToCopy内先赋予文件777的权限,再重启容器重新映射。
如果通过宿主机目录dllToCopy无法成功映射,可以进入容器,在dllToCopy下直接创建对应目录,然后退出容器再通过命令将文件拷贝到新建目录下。拷贝完成之后重启容器,容器中dllToCopy目录下的文件依然会自动覆盖到IoTCenter目录下对应的文件夹中。
例如: 需要将AlarmCenterProperties.xml文件直接拷贝进容器。
- 首先进入容器,在/opt/ganwei/IoTCenter/dllToCopy下创建/data/AlarmCenter
- 然后exit命令退出容器,执行文件拷贝命令:
kubectl cp AlarmCenterProperties.xml iot/iotcenter-euler-v1-7c8fc767b6-2qc8t:/opt/ganwei/IoTCenter/dllToCopy/data/AlarmCenter
映射和拷贝的区别在于:当我们修改宿主机映射目录文件的时候,重启容器,改动会同步更新到容器内部;而修改容器外的拷贝文件则不会对容器内部产生影响。
# 更新方法
# 更新dll文件
如果需要更新容器内/opt/ganwei/IoTCenter/dll/的文件。 在宿主机/var/hicampusdata/gwiotcenter/dllToCopy下创建一个dll目录
然后把文件拷贝到新创建的dll文件夹内,重启容器,更新完成。
# 更新应用插件
在宿主机/var/hicampusdata/gwiotcenter/dllToCopy下创建IoTCenterWeb/packages目录,将需要更新的插件拷贝到新建的packages文件夹内,重启容器。 注:如果最初没有这个插件,更新进去之后并不会解压安装,需要将容器中IoTCenter/IoTCenterWeb/packages目录下的manifest.json文件拷贝出来进行修改,将修改后的文件再拷贝到宿主机dllToCopy/IoTCenterWeb/packages目录中,重启容器完成更新。
# 许可更新说明
# 通过dllToCopy目录映射更新许可
映射方法参考目录4.1(文件更新) 授权文件映射成功,重启容器,之后的操作流程如下
# 加密数据库连接字符串
详情
进入容器,使用bin目录下的加密工具把数据库连接字符串加密。
退出容器,修改configmap文件的对应配置项,命令如下:
kubectl edit cm ioteuler-euler-cm -niot
保存之后重启容器,完成更新。
调试环境下,也可采用以下方法: 将容器内AlarmCenterProperties.xml配置文件拷贝到宿主机
kubectl cp iot/iotcenter-euler-v1-7c8fc767b6-2qc8t:/opt/ganwei/IoTCenter/data/AlarmCenter/AlarmCenterProperties.xml ./AlarmCenterProperties.xml
手动修改拷贝出的AlarmCenterProperties.xml文件,修改加密字符串。
在nfs宿主机/var/hicampusdata/gwiotcenter/dllToCopy下新建data\AlarmCenter目录,将修改完的AlarmCenterProperties.xml文件放到data\AlarmCenter下,重启容器。
# 更新用户数据表
首先删除gwuser表旧的用户数据,更新数据库用户为原始数据(6.0.2版本无需更新为原始数据,只要删除老的用户数据,就会自动导入新用户数据并加密)。 然后将容器内publish/appsetting.json文件拷贝到宿主机,手动修改文件中的节点IsAesUpdateSuccess为false。
修改完成之后将文件拷贝到nfs服务器的映射目录dllToCopy/IoTCenterWeb/publish下,重启容器,用户原始数据会自动加密。
# 排查其它的加密数据
若有其它涉及加密的数据都要重新进行加密,对于文件型的加密数据都要做好映射。 需要重新加密的数据包括:
名称 | 位置 | 用途 | 备注 |
---|---|---|---|
数据库连接密码 | AlarmCenterProperties.xml配置文件 | 连接数据库 | |
登录账号和密码 | gwuser数据库表 | 账号密码加密 | |
用户角色 | gwrole数据库表 | 角色加密 | |
应用secret | 北向应用接入管理 | southSecret配置值 | |
RomaSDK | jar包config.properties配置文件 | huawei.ump.producer.appSecret配置值 |
# 通过更新iotcenter-configmap.yaml文件更新许可
# 更新yaml文件中的许可信息
打开iotcenter-configmap.yaml文件,将获取的新的授权信息替换到这个文件中。
# 更新容器中的yaml文件
详情
首先将下图所示的修改好的两个yaml文件拷贝到服务器
然后我们删除旧的iotcenter-deployment.yaml 文件 命令:
kubectl delete deploy iotcenter-euler-v1 -niot
然后更新iotcenter-configmap.yaml文件 命令:
kubectl apply -f iotcenter-configmap.yaml -niot
之后再更新iotcenter-deployment.yaml文件 命令:
kubectl apply -f iotcenter-deployment.yaml -niot
# 验证新的授权文件
进入容器内的bin目录下查看AlarmCenter.shd授权文件有没有更新成功。
# 端口映射
# 如何自定义域名解析
详情
有些项目中需要用到域名解析服务,这样需要在环境中配置hosts域名解析服务,教程利用了kubernetes提供的HostAliases来实现。 首先通过输入命令查找deploy资源文件。
如上图查找到资源文件为iotcenter-euler-v1的资源名称,输入如下命令,进入ymal文件的编辑模式:
kubectl edit deploy iotcenter-euler-v1 -niot
在如图所示位置添加(每一行要严格对齐)
hostAliases:
- hostnames: [ "域名" ]
ip: "ip地址"
之后保存即可,添加后在容器内可以看到 hosts 被添加到了/etc/hosts中,如下图所示
# 如何映射新的端口
详情
kubernetes中一个服务可以存在一个或多个pod(容器),kubernetes提供service资源对一个或者多个pod进行聚合,提供统一的出入口,所以需要从服务中映射端口,需要在service的资源文件中进行添加。各参数关系如下图所示。
首先通过命令查找所要修改服务的service名称;
kubectl get service -niot
输入命令
kubectl edit service iotcenter-euler-v1 -niot
之后在ports;下面按照图中红色方框为一个端口映射进行添加。
比如,将容器中的44380端口映射到30380
属性 | 示例 | 说明 |
---|---|---|
name | https-44380-4438 | 名称可以自定义 |
nodePort | 30380 | 映射出的端口 |
port | 44380 | 被映射端口 |
protocol | TCP | 映射协议 可以选择TCP |
targetPort | 44380 | 容器被映射的端口 |
要注意的是nodeport这个参数范围,kubernetes集群默认端口范围为30000-32767 修改过程的错误;如下图所示,第一个错误是外部端口被占用,第二个错误则是端口没有在30000-32767这个范围内
# 数据库维护
# 确定数据库位置
详情
首先需要确定pod所在的服务器。 输入
kubectl get pod -niot -o wide
通过SSH工具登录数据库pod所在的集群机器。 输入
kubectl get pod -niot
输入
kubectl exec -it pod名字 -niot bash
进入数据库容器。
# mysql备份数据库
详情
mysqldump -u root -p iotcenter > 1bak.sql
输入密码:密码见附录密码存储文件
查看备份
将备份的数据库脚本从pod中拷贝出来(容器外) 执行
kubectl cp mysql-v1-xxxxx:var/lib/mysql/bak1.sql ./bak1.sql -niot
# mysql恢复数据库
详情
将数据库脚本拷贝到新部署环境中的pod中 输入
kubectl get pod -niot 查询pod名称
kubectl cp bak2.sql mysql-v1-xxxxx:var/lib/mysql/bak2.sql -niot
进入新部署的环境中的pod 输入
kubectl exec -it pod名字 -niot bash
之后进入数据库容器, 在容器中输入
cd /var/lib/mysql/
进入目录 之后输入
mysql -uroot -p
接着输入密码:密码见附录密码存储文件
接着输入
show databases;
可以看到一个名称叫iotcenter的数据库
输入
use iotcenter
进入数据库, 然后通过source命令,将备份数据库导入到iotcenter数据库
source /var/lib/mysql/bak1.sql
回车即可将备份的文件导入到iotcenter数据库中, 接着将iotcenter 的pod 删除一次,
# Gaussdb备份数据库
详情
进入pod,后输入 su – omm
之后输入一下命令备份iotcenter数据库完成数据库的备份。
gs_dump -U gaussdb -f /home/omm/iotcenter.tar -p 5432 iotcenter -F t
输入密码:输入密码:密码见附录密码存储文件
查看备份
将备份的数据库脚本从pod中拷贝出来(容器外)
kubectl cp opengaussdb-v1-xxxxx:home/omm/iotcenter.tar ./iotcenter.tar -niot
# Gaussdb恢复数据库
详情
将数据库脚本拷贝到新部署环境的pod中, 输入
kubectl get pod -niot
查询pod名称, 输入以下命令将备份拷贝到容器中
kubectl cp iotcenter.tar opengaussdb-v1-xxxxx:var/lib/mysql/ iotcenter.tar -niot
输入 kubectl exec -it pod名字 -niot bash 之后进入数据库容器,
输入
cd /home/omm/
切换到此路径 先给iotcenter 提升一下权限
chmod 777 iotcenter.tar
输入su omm切换到omm 用户
输入视频
gs_restore -U gaussdb iotcenter.tar -c -p 5432 -d iotcenter
输入密码:输入密码:密码见附录[**密码存储文件**](../附录/README.md),
回车即可将备份的文件导入到iotcenter数据库中。
将iotcenter 的pod 删除重启
# 镜像升级
详情
使用docker id 重命名镜像
docker tag 2bf4ecf9fed5 mydockerhub.com:5000/cube-repo-space/iotcenter:6.0.1
检查deploy文件,确保镜像调用路径与镜像名称一致
kubectl get deploy -niot
kubectl edit deploy iotcenter-euler-v1 -niot
重启pod,升级完成
kubectl delete pod iotcenter-euler-v1-7c8fc767b6-wldzl -niot
4.5.2. OpenGauss镜像升级
gs_restore -U gaussdb iotcenter.tar -c -p 5432 -d iotcenter