文章目录
- 第一阶段
- 第二阶段
- 第三阶段
- Docker
- Ansible
- K8S
- K8S 二进制搭建
- K8S kubeadm搭建
- kubeadm 部署的K8S集群更新证书
- K8S 3种网络
- K8S 3种接口
- flannel 3种模式
- flannel UDP模式工作原理
- flannel VXLAN模式工作原理
- Calico IPIP模式工作原理
- Calico BGP模式工作原理(本质就是通过路由表来维护每个 Pod 的通信)
- flannel 和 calico 区别?
- 陈述式资源管理
- service 的 4 种类型:
- service 的端口:
- 如何获取资源配置清单文件模板(yaml配置文件)
- 一个pod能包含几个容器?
- pause容器的作用?
- Pod 的 3 种类型:
- Pod 的 3 种容器:
- Pod 的 3 种镜像拉取策略: spec.containers.imagePullPolicy
- Pod 的 3 种容器重启策略: spec.restartPolicy
- Pod 容器的资源限制
- Pod 容器的 3 种探针(健康检查)
- 探针的 3 种探测方式
- 探针参数:
- Pod 应用容器生命周期的启动动作和退出动作
- K8S是通过 List-Watch 机制实现每个组件的协作
- scheduler 的调度策略
- Pod 调度到指定的 Node节点
- 标签的管理操作
- 亲和性
- 如何判断是否在同一个拓扑域?
- 亲和性的策略
- 污点 taint
- 容忍 tolerations
- 不可调度
- 不可调度 + 驱逐
- Pod 的启动过程:
- Pod 生命周期的 5 种状态
- K8S 中的排障手段
- K8S 的 存储卷 volumes
- PV PVC
- 创建 PV 的方式(PV的类型):
- PV 的 4 种状态:
- 创建使用 静态PV
- 创建使用 动态PV
- pod的 5 种控制器:
- 有状态服务和无状态服务的区别
- configmap
- Secret资源的 4 种类型:
- 创建 Secret资源
- 使用 Secret资源
- 陈述式管理资源的方式 修改或添加 资源对象的配置
- K8S集群外的客户端应用访问K8S集群内部服务的方案
- ingress 的组成:
- ingress 的使用:
- ingress 的配置
- 基于 https 代理转发
- 基于 basic-auth 访问认证
- 基于 rewrite 重写访问路径
- pod 的自动伸缩
- K8S 的安全机制
- 如何授权让一个普通用户能够使用 kubectl 在 K8S 中具有操作资源权限?
- Helm 是K8S的软件包(Chart包)管理器
- Helm 的三大概念:
- Helm 仓库管理命令:
- chart包的关键组成:
第一阶段
平常怎么处理故障,思路是什么样的
看故障现象根据经验就知道原因;
第一次碰到,先定位问题,故障不一定是我的问题,开发、测试、硬件、网络,也可能我的问题;如果问题在我,根据错误提示信息、系统日志、错误日志去分析问题。
系统问题可以用top看cpu、df看磁盘、uptime看负载、ps看进程、sar看流量。
应用程序就是看日志提示解决问题,如果是开发问题,可以通过邮件等方式,描述故障现象和定位过程发送给开发对接人和我的领导。
如果是网络问题,路由、交换机可以找网络工程师,可以抓包tcpdump;
如果是硬件问题,可以找厂商。
公网和私网分类以及范围,本机地址,网络地址,广播地址
公网
A:1.0.0.1~126.255.255.254/18
B:128.0.0.1~191.255.255.254/16
C:192.0.0.1~223.255.255.254/24
D:224.0.0.1~239.255.255.254
E:240.0.0.1~255.255.255.254
私网
10.0.0.0~10.255.255.255
172.16.0.0~172.31.255.255
192.168.0.0~192.168.255.255
其他
169.254.0.0~169.254.255.255 DHCP失效时分配的网址
127开头的都是本机 127.255.255.255除外 它是广播地址
224.0.0.18 VRRP协议交换机侦听此地址
交换机的工作原理
1)交换机开机时MAC地址表没有任何记录
2)源主机通过交换机发送数据帧给目标主机,交换机学习数据帧中的源MAC和对应接口标识并记录到MAC地址表中
3)如果交换机的MAC地址没有目的MAC地址所对应的接口记录,则会进行广播泛洪
4)只有拥有对应的MAC地址的主机才会进行回应响应
5)交换机会从目的主机回复的消息中学习到MAC地址和对应的接口标识并记录到MAC地址表中,之后两台主机可以通过交换机的MAC地址表进行单播通信
交换机通过MAC地址表的记录实现数据帧的转发,MAC地址表默认老化时间300S
ICMP是什么干什么用的,它有哪些命令
是一个错误侦测与回馈机制,发送错误和控制消息来探测节点的网络连通性
ping
pathping 例子:pathping www.baidu.com 跟踪数据包路径,计算机丢包情况
traceroute
TCP和UDP协议的区别
TCP UDP
可靠性 可靠 不可靠
连接性 面向连接 无连接
报文 面向字节流 面向报文(保留报文的边界)
效率 传输效率低 传输效率高
双工性 全双工 一对一、一对多、多对一、多对多
流量控制 有(滑动窗口) 无
拥塞控制 有(慢开始、拥塞避免、快重传、快恢复) 无
tcp有哪些控制位,分别是什么意思
URG 紧急位
ACK 确认位
PSH 急迫位
RST 重置位
SYN 同步(连接)位
FIN 断开位
你是用过哪些Linux命令
性能监控方面: free 查看内存 top 动态监控cpu 负载 等 df 查看磁盘使用 ps 查看进程 iostat 查看io
用户方面:useradd 创建用户 chmod 修改权限 chown 设置归属
查询方面: sed grep awk cat more less which whereis
Linux 系统安全优化与内核优化
安全优化: 设置防火墙规则 限制root 用户远程登录 设置历史命令条目及登录超时 chattr锁定文件 时间同步 配置yum更新源
内核系统优化:
sysctl.conf 文件中 net.ipv4.ip_forward 设置路由转发 net.ipv4.tcp tw recycle = 1 开启time-wait 快速回收 net.ipv4.ip_local_port_range = 1024 65000 设置外向连接端口范围 /etc/security/limits.conf nofile 设置文件最大打开数 nproc 设置最大进程数 rss 设置最大常驻集大小 menlock 锁定内存地址空间
经常使用shell脚本做什么
使用shell脚本进行重复性的操作
一键部署公司的业务服务
日志的监控和分割 备份 配置crontab -e 进行计划性任务
巡检
软连接与硬链接的区别
硬链接与源文件共享inode ,也就是说,他们都指向同一份数据,占用的磁盘空间也相同,删除一共硬链接并不影响源文件内容和其他硬链接,相当于给文件起了一共别名
软连接与源文件不仅inode不同,源文件删除了。软连接也就失效了,类似于一个快捷方式、
怎么查看文件
find 查找文件
locate 查找系统中已经建立的文件索引库
whereis 可以查找指定命令的二进制文件、源代码文件
which 查找命令所在的目录
IOS七层模型
- 物理层
- 数据链路层
- 网络层
- 传输层
- 会话层
- 表示层
- 应用层
三次握手与四次挥手
三次握手 : pc1 向 pc2 发送一个 SYN 报文,pc 回复一个 SYN + ACK 报文 pc1 再次发送一个ACK报文
四次挥手: pc1发送一个FIN / ACK 报文给pc2 (此时pc1客户端进入等待断开连接状态)
pc2接收到pc1发送的请求断开报文之后回复一个ACK报文进行确认
pc2紧接着发送一个FIN / ACK 报文给pc1(此时pc2客户端进入等待断开连接状态)
pc1收到后发送ACK报文进行确认 (此时pc1进入时间等待状态 60秒后默认结束)
lvm 逻辑卷创建过程
- 创建一个物理卷: pvcreate 设备名(可创建多个)
- 创建卷组 : vgcreate 卷组名 物理卷名
- 创建逻辑卷: lvcreate -L 容量大小 -n 逻辑卷名 卷组名
- 扩展卷组:先扩展物理卷 在使用 vgextend 卷组名 设备
- 扩展逻辑卷 : 随后使用 lvextend -L + 容量大小 /dev/卷组名/逻辑卷名
- 格式化 挂载使用·
磁盘配额
- 首先检查是否安装 xfsprogs 和 xfs_quota
- 以支持配额的方式进行挂载文件系统 mount -o usrquota,grpquota /dev/vgname1/lvname1 /opt 或者永久挂载/ dev / vgname1 / lvname1 / opt xfs defaults,usrquota, grpquota 0
- 对用户和组账号进行配额限制 xfs_quota -x -c 'limit -u bsoft-80M bhard-100M isoft=40 ihard=50 lisi’ /opt/
- 验证用户在限制目录下的使用
raid 磁盘阵列
raid 0 条带化存储 传输速率达到单个硬盘的N 倍 但它没有数据冗余
raid 1 镜像存储 实现数据冗余 但利用率为N/2
raid 5 N>=3 块盘组成 利用率 (N-1)/N (其中有一块是用来校验的)
raid 6 N>=4 块盘组成 (N-2)/ N (有两块盘用来校验)
raid 1 0 先做镜像 再做条带 利用率 N/2
文本三剑客
grep :
-i 不区分大小写
-v 取反
-n 显示行号
-r 递归过滤文件夹中的所有内容
-w 只显示全部字符的列
-l 列出文件内容符合指定的样式文件名称
sed :
-i 替换:s 对指定的内容进行替换
d 删除选定的行
a 在当前行的下面增加一行内容
i 在当前行的上面增加一行内容
c 替换选定行为指定内容
y 字符转换 转换前后的字符必须长度相同
awk:
FS 列分隔符
NF 当前处理行的字段个数
NR 当前处理行的序号
RS 行分隔符
防火墙iptables与fireward
四表:raw 表 mangle表 nat 表 filter 表
五链:INPUT 链 OUTPUT 链 FORWARD 链 PREROUTING 链 POSTROUTING 链
firewalld防火墙9大区域:trusted(信任区域) public (公共区域) home (家庭区域) internal (内部区域) work (工作区域) dmz(隔离区域) block (限制区域) drop (丢弃区域)
Linux系统资源查询命令
free 查看交换空间内存状态
cat /etc/redat-release ; cat /etc/*release ; cat /proc/version 查看当前系统版本
uname -r 查看内核版本
cat /proc/cpuinfo、sar、 lscpu 查看cpu 信息
vmstat 查看系统内存 、交换空间、io、cpu 信息
iostat 查看磁盘io性能
top 动态的查看当前进程信息 cpu负载信息 内存信息
uptime 、 w 显示系统运行时间,登入用户和cpu负载情况
cat /proc/meninfo 查看内存
ps -T top -H 查看线程
日志的八大等级
emerg 紧急
alert 警告
crit 严重
err 错误
warning 提醒
notice 注意
info 信息
debug 调式
Linux 引导过程
- 开机自检
- MBR引导
- Grup 菜单
- 加载linux内核
- init进程初始化
shell 函数的创建方法
函数名 () {
}
function 函数名 {
}
免交互的使用
EOF 进行免交互
EXPECT 进行免交互:
申明脚本解释器
2. swap 开启一个会话 3. expect 进行匹配 字符 4. send 代表输入字符 5. 结束符 expect eof
你是用过哪些shell脚本
Tcpdump抓包使用工具
-i : 指定 tcpdump 监听的网络接口
-s : 指定要监听的数据包的长度
-c : 指定要监听的数据包数量 ,达到数量后自动停止抓包
-w : 指定将监听到的数据包写入文件中保存
-n : 将每个监听到的数据包中的域名转换成 IP 地址后显示
CPU过高怎么解决
用 top 命令查看哪个进程 cpu 使用过高
再用 top -H -p 显示特定进程中的线程,锁定cpu使用过高的线程
看这个进程是否是业务进程,不是直接kill 掉即可
如何杀死僵尸进程
先用top 命令查看是否具有僵尸进程
再红色表示的地方,如果 zombie 大于0 表示服务器当前存在僵尸进程
ps -A -o stat,ppid,pid,cmd | grep -e ‘1’
什么是中间件?什么是 JDK
中间件
他是一种独立的系统软件或服务程序,分布式应用软件借助他在不同技术之间共享资源
中间件位于客户机/服务器的操作系统之上,管理计算机资源和网络通讯
JDK
是java开发工具包
他是一种用于构建再java平台上发布的应用程序,applet和组件的开发环境
什么是CDN
CDN 是内容分发网络,
工作原理: 将您源站的资源缓存到位于全球各地的CDN节点上,用户请求资源时,就近返回节点上缓存的资源,而不需要每个用户的请求都回你都源站获取,避免网络堵塞、缓解源站压力,保证用户访问资源的速度和体验
第二阶段
http
http 的版本
http 1.0 纯文本传输;http响应后会立即关闭TCP连接;支持http头部信息(比如http协议版本号,状态码等)
http/1.1:支持长连接(连接保持,持久连接)和管道机制(在一TCP连接中实现多个http请求和响应)
http/2.0:二进制传输;支持长连接和完全多路复用(在一个TCP连接中同时发送多个请求,且不用按照顺序一一对应);支持网页头部压缩,支持服务端主动推送
http/3.0:基于UDP协议的
http 响应状态码
200 一切正常
301 永久重定向
302 临时重定向
401 用户名/密码错误
403 拒绝访问
404 文件不存在
500 服务器内部错误
502 错误网关
503 服务不可用
504 网关超时
Nginx
Nginx 的常用模块有哪些?
gzip 压缩模块
rewrite 重写模块
upstream 负载均衡模块
proxy 代理模块
status 状态统计模块
ssl ssl模块加密http连接
auth_basic 认证模块
Nginx 的 session 不同步怎么办
可以采用 ip_hash 指令解决这个问题,如果客户已经访问了某个服务器,当客户再次访问时会通过hash算法,自动定位到该服务器。即每个访客固定访问一个后端服务器,可以有效解决session 的问题
其他方法: 采用 spring_session+redis ,把session放入到缓存中实现session共享
nginx的优化
配置文件优化:
- 配置网页压缩
- 隐藏版本号
- 设置缓存事件
- 设置工作进程数
- 设置连接保持
- 设置并发
- 防盗链
- 日志分割
系统内核级别优化:
/etc/security/limits.conf:
- 打开文件数 nofile
- 打开进程数 nproc
- 内存锁定不限制 memlock
- 最大常驻集 rss
/etc/sysctl.conf
- 开启 SYN cookies
- 允许将time-wait 重新应用于新的TCP连接
- 开启 TIME-WAIT sockets 快速回收
- 设置系统同时保持time wait 最大数量
- 发送keepalive探测包消息的频度
- 外向连接端口范围
Nginx如何实现动静分离
服务端接收来自客户端的请求中,既有静态资源也有动态资源,静态资源由Nginx提供服务,动态资源则由Nginx转发至后端服务器处理(tomcat);Nginx作为负载均衡器以及反向代理
在Nginx上配置反向代理(七层),在Http项里面先配置upstream+服务器地址池名称大括号{}里面配置地址池,server+后端服务器的IP:端口,可以配置权重或者负载均衡策略ip_hash
然后在server项中再配置location项匹配以.jsp结尾的动态页面则使用proxy_pass http://+服务器地址池名称进行转发,其他静态页面则交给Nginx出来处理
Nginx反向代理有哪些方式实现,有什么区别 ?如何配置
四层反向代理: 基于ip和端口进行转发
首先要加载stream 模块,stream 模块与http同级,所以一般配置在http上面,需要配置upstream服务器池和监听端口以及代理转发
先配置upstream+服务器地址池名称{}大括号里面定义地址池:server +后端服务器的IP以及端口,还可加上权重或者负载均衡策略
再配置server项,server{}大括号里面配置监听端口以及proxy_pass+服务器地址池名称进行转发
七层方向代理: 基于http、https、mail进行转发
要配置在http里面,来配置upstream服务器池与server项配置。先配置upstream+服务器地址池名称大括号{}里面配置地址池:server+后端服务器的IP:端口,可自定义权重或者负载均衡策略
再配置server项中的location项匹配以.jsp结尾的动态页面则使用proxy_pass http://+服务器地址池名称进行转发给后端服务器tomcat,其他静态页面则交给Nginx来处理
Nginx 负载均衡调度算法有哪些?
- 轮询
- 加权轮询
- 最少链接
- ip_hash
- url_hash
- fair
tomcat知识点
tomcat 三个端口号
- 8005 关闭tomcat通信端口
- 8080 http访问的端口号
- 8009 AJP协议访问端口 ,容器使用
tomcat 优化
配置文件优化: maxThreads (最大线程数) acceptcount (等待队列数) enablelookups (关闭dns反向解析) maxkeepaliverequests (连接保持最大请求数) connectiontimeout (连接超时时间) compression (开启网页压缩)
系统内核优化: /etc/security/limits.conf : 打开最大文件数 、打开最大进程数、锁定内存地址空间、rss 最大持久设置大小
/etc/sysctl.conf: 开启tcp连接中time-wait 快速回收、允许time-wait sockets 重新用于新的tcp连接、外向连接端口范围
JVM 优化: 设置堆内存初始值和堆内存最大值(一般为物理内存的1/2) 设置非堆内存和最大非堆内存(一般为物理内存的1/4)、
LVS
LVS、Nginx、Haproxy 有什么区别?
- LVS 可实现4层负载均衡,无法基于目录、url 转发,而Haproxy和nginx都可以实现4层和7层
- lvs其状态检测功能单一、而haproxy在监测方面功能更加丰富、强大、可支持端口、url 脚本等多种状态检测
- haproxy 功能强大、但整体性能低于4层的lvs负载均衡
- nginx 主要用于web服务器或缓存服务器
简述LVS三种模式 以及工作中使用哪种模式
NAT 地址转换
调度器会作为所有节点服务器的默认网关,也是客户机的访问入口和节点服务器返回响应消息的出口,也就是说调度器会承载双向数据的负载压力,可能会成为整个群集的性能瓶颈。
由于节点服务器都处于内网环境,使用私网IP地址,所以安全性尚可。
TUN IP隧道 IP Tunnel
调度器仅作为客户端的访问入口,节点服务器的响应消息是直接返回给客户端的,不经过调度器
由于节点服务器需要部署在不同位置的公网环境中,需要具有独立公网IP,调度器与节点服务器是通过专用的IP隧道实现相互通信的,因为IP隧道模式的成本较高、安全性较低,且IP隧道需要更多的封装和解封装过程,性能也会受到一定的影响
DR 直接路由 Direct Routing
调度器仅作为客户端的访问入口,节点服务器的响应消息是直接返回给客户端的,不经过调度器,节点服务器与调度器是部署在同一个局域网内,因此不需要建立专用的IP隧道。DR模式是企业的首选模式。
NAT模式配置注意点
客户端和节点服务器 的默认网关要指向 调度器的IP
调度器要设置 IP路由转发 和 SNAT 等 iptables 规则
调度器安装 ipvsadm 配置 虚拟服务器 和 真实节点服务器
DR模式配置注意点
节点服务器要在 lo:0 上配置VIP , 修改内核参数 arp_ignore = 1 arp_announce = 2 , 添加路由
调度器要在 ens33:0 上配置VIP , 修改内核参数关闭ip路由转发和重定向功能
调度器安装 ipvsadm 配置 虚拟服务器 和 真实节点服务器
keepalived
脑裂的原因,如何解决
什么是脑裂
- 相互之间失去了联系,都误以为对方挂掉了,两个节点像脑裂一样抢占资源 ,最终导致出现了两个master
都有哪些原因导致脑裂
- 链路出现了问题,导致无法正常通信
- 高可用服务器开启了防火墙从而阻挡了心跳消息的传输
- 高可用心跳网卡地址等信息配置不正确,导致发送心跳失败
解决方法
- 增加一条链路,作为备用链路
- 通过脚本的方式解决
- 通过第三方监控软件方式解决,既监控服务器状态,也监控网络流量
简述 keepalived 如何通过健康检查来实现高可用?
mysql
sql 语句
show databases; 查看数据库
show tables; 查看库中的表
desc 表名; 查看表的结构
create database 数据库名; 创建新的数据库
create table 表名 (字段1 数据类型, 字段2 数据类型) 创建新的表
drop table 表名; 删除表
drop database 数据库; 删除库
select 字段1,字段2 from 表名;查询表的记录
update 表名 set 字段名1=字段1;修改,更新数据表中的数据
delete from 表名 【where 条件表达式】; 删除指定数据
alter table 旧的表名 rename 新的表名 ; 修改表名
alter table 表名 add 字段 数据类型 default ‘默认值’ ;扩展表结构(增加字段)
ater table 表名 change 旧列名 新列名 数据类型 ;修改字段名
alter table 表名 drop 字段名; 删除字段
create user ‘用户名’@‘来源地址’ 【identified by ‘密码’】 ; 创建用户
select user(); 查看当前登录用户
DROP USER ‘用户名‘@’来源地址‘ 删除用户
SET PASSWORD = PASSWORD(‘abc123’); 修改当前用户密码
grant 权限列表 on 数据库名 . 表名 to ’用户名@来源地址‘; 给用户授权
show grants for ’用户名‘@’来源地址‘; 查看权限
revoke 权限 on 库名 . 表名 from ’用户‘@’来源地址‘; 撤销权限
mysql> create table if not exists 快餐 (
-> id int(4) zerofill primary key auto_increment,
-> name char(4) not null default'匿名',
-> phone varchar(11) unique key);
#if not exists:表示检测要创建的表是否已存在,如果不存在就继续创建
#int(4) zerofill:表示若数值不满4位数,则前面用“0”填充,例0001
#auto_increment:表示此字段为自增长字段,即每条记录自动递增1,默认从1开始递增;自增长字段数据不可以重复;自增长字段必须是主键;如添加的记录数据没有指定此字段的值且添加失败也会自动递增一次
#unique key:表示此字段唯一键约束,此字段数据不可以重复;一张表中只能有一个主键, 但是一张表中可以有多个唯一键
#not null:表示此字段不允许为NULL
克隆表
方法一:
create table ggb like mdl; #通过 LIKE 方法,复制 KY08 表结构生成 test01 表
insert into ggb select * from mdl;
#此方法能保证 新表的表结构、表数据 跟旧表都是一致的
方法二:
CREATE TABLE zzx (SELECT * from mdl);
#此方法创建的新表的表数据和旧表是一样的,但可能会出现新表的表结构和旧表的不一致
清空表数据
方法一:
delete from ggb;
#DELETE清空表后,返回的结果内有删除的记录条目;DELETE工作时是一行一行的删除记录数据的;如果表中有自增长字段,使用DELETE FROM 删除所有记录后,再次新添加的记录会从原来最大的记录 ID 后面继续自增写入记录。
方法二:
truncate table mdl;
#TRUNCATE 清空表后,没有返回被删除的条目;TRUNCATE 工作时是将表结构按原样重新建立,因此在速度上 TRUNCATE 会比 DELETE 清空表快;使用 TRUNCATE TABLE 清空表内数据后,ID 会从 1 开始重新记录。
Mysql 六大约束
primary key 主键约束
foreign key 外键约束
not null 非空约束
unique key 唯一键约束
default 默认值约束
auto_increment 自增约束
遗忘 root 密码的解决方法
vim /etc/my.cnf 添加 skip-grant-tables 使登录mysql不适用密码验证
登入数据库后 使用 update mysql.user set AUTHENTICATION_STRING = PASSWORD(‘abc123’) where user=‘root’;
flush privileges; 即可
索引的作用
索引的作用就是加快表的查询速度,同时对表的字段进行排序
索引的创建
create unique index 索引名 on 表名(列名); 直接创建唯一索引 alter table 表名 add index 索引名(列明); 修改表结构进行添加索引
create unique index 索引名 on 表名(列名); 直接创建唯一索引 ALTER TABLE 表名 ADD UNIQUE 索引名 (列名); 修改表结构创建唯一索引
ALTER TABLE 表名 ADD PRIMARY KEY (列名); 创建主键索引
mysql 事务的 ACID 特性与四种隔离
ACID : 原子性 一致性 隔离性 持久性
四种隔离: 提交读 不可提交读 可重复读 穿行读
死锁的产生原因与解决方法
死锁一般是事务相互抢占对方资源,最后形成环路造成的
解决方法:
- 使用更合理的业务逻辑,
- 大事务拆小
- 在同一个事务中,最好做到一次锁定所有需要的资源,减少死锁概率
- 降低隔离级别
- 为表添加合理的索引
mysql 主从复制原理
- 主服务器开启二进制日志 ,从服务器开启中继日志
- 主服务器写入数据到二进制日志当中,从服务器开启 io 线程 像主服务器请求的二进制日志事件
- 主服务器为每一个io线程开启一个dump 线程发送二进制日志事件,从服务器将接收的二进制日志事件保存到自己的中继日志当中
- 在 mysql 5.7 版本之后 主服务器会开启一个ack connection 线程来接收从服务器发来的确认信息
- 从服务器开启 sql 线程 将中继日志的二进制日志事件解析成 sql 语句并进行重放逐一执行
主从复制的部署过程
1.配置时间同步
2.主服务器开启二进制日志,从服务器开启中继日志
3.主服务器使用grant replication给从服务器进行授权
4.从服务器是使用change master与主服务器建立同步连接
5.从库开启同步 start slave;
6.使用show slave status\G;查看同步连接状态
MHA 高可用
MHA 集群中需要部署 node 节点和 manager 节点,所有服务器上都需要部署 node 节点,manager节点可以部署在一台单独的服务器上,manager 会监控集群中的master 节点,当 master 出现故障时,它会自动将
拥有最新数据的slave 节点升级成新的master 节点, 然后将所有的其他的slave 重新指向新的master ,并且故障转移后会将故障主机的信息移除,具体可以通过vip 的飘逸查看,整个故障转移过程都是透明的。
MHA 部署过程
1.所有服务器都开启二进制日志和中继日志
2.所有mysql节点都做主从复制的用户授权,数据库用户的授权
3.配置时间同步和Mysql主从复制,并设置从库为只读模式
4.安装MHA的依赖环境、epel源;修改所有主机Myid不能一致
5.在所有服务器上先安装node组件,在manager节点上安装manager组件
6.所有服务器配置ssh无密码验证
6.在manager节点上准备好,故障切换脚本,和manager进程配配置文件
7.第一次配置需要在master节点后端开启虚拟IP,使用ifconfig创建VIP
8.测试主从连接情况;测试故障切换,SSH无密码认证
MMM 高可用
mysql-mmm 的监管端会提供多个虚拟 IP(VIP),包括一个可写 VIP,多个可读 VIP,通过监管的管理,这些 IP 会绑定在可用 MySQL 之上,当某一台 MySQL 宕机时,监管会将 VIP 迁移至其他 MySQL。
mysql 数据库的优化
硬件方面: cpu: 推荐使用 4u 的服务器专门做数据库服务器
内存: 推荐使用 4Gb 以上的物理内存
磁盘: 磁盘 I/O 是制约 mysql 性能的最大因素之一、 通常使用 RAID 0+ 1
配置文件: 开启查询缓存,慢查询日志,优化查询
使用 explain 判断 select 查询,从而分析查询语句或是表结构的性能瓶颈,然后针对性的进行优化
为搜索字段建索引
对于有限定范围取值的字段,推荐使用ENUM 而不是 VARCHAR
垂直分表
选择正确的存储引擎
(1 ) sync_binlog=1 双1 设置在每写一次二进制日志时都会同步到磁盘中去
(2 ) innodb_flush_log_at_trx_commit=1 双1 每次事务提交时 MYSQL 都会把缓存的数据写到日志文件,并且刷新到磁盘中
(3 )max_connect_errors=6000 设置每个主机的连接请求异常中断的最大次数
(4) max_connections = 5000 mysql 允许最大的进程连接数
Mysql 数据库 cpu 飙升到 500% 怎么处理
当cpu 飙升到500%时 ,先用操作系统命令 top 查看是不是mysql 占用导致的,如果不是,找出占用高的进程并进行处理。
如果是mysql导致的,使用 show processlist 看看里面跑的 session 情况 ,是不是有消耗资源的sql 在运行,找出消耗资源高的sql,看看执行计划是否准确,index 是否缺失,或者是数据量太大造成、。
一般来说,肯定要先kill 掉这些线程同时观察cpu使用率是否下降,在进行相应的调整,比如添加索引,修改sql语句 改内存参数之后再重新跑这些sql
也有可能每个sql 消耗的资源并不多,但是突然间有大量的session链接进来导致cpu飙升,这种情况就需要应用一起来分析为何连接数会激增,在做出相应的调整,比如限制连接数等
但是比如吞吐量下降 、查询响应时间增加、慢查询数增加 也会造成上述影响
Mysql 数据库备份
mysqldump 进行备份
完全备份:
mysqldump -uroot -p --all-databases > xxx.sql
--databases 库 备份库
库名 表1,表2 备份库中的表
完全恢复:
mysql -uroot -p < xxx.sql
增量备份:
mysqladmin -uroot -p flush-logs
增量恢复:
mysqlbinlog --no-defaults 二进制文件 | mysql -uroot -p
redis
redis 为什么读写速度那么快?
- redis 是一款纯内存结构,避免了磁盘 i/O 等耗时操作
- redis 是单线程,减少了线程上下文切换的消耗
- 采用了 I/O 多路复用机制,大大提升了并发的效率
redis 常用的数据结构
- string 字符串
- list 列表
- hash 哈希
- set 集合
- zset 有序集合
redis 持久化
RDB 持久化 : 采用定时快照的方式对文件进行压缩存储到磁盘当中
AOF 持久化 : 采用 实时追加的方式将redis写的操作记录到文件当中
redis 哨兵
- 由哨兵节点定期监控发现主节点是否出现故障,每一个哨兵节点每隔一秒会向主节点、从节点以及其他哨兵节点发送一次ping命令做心跳健康检测,如果主节点再一定时间内没有回复或者回复一共错误消息,那么这个哨兵节点则认为主节点主管下线了,当超过半数的哨兵节点认为主节点客观下线,那么将会主观下线。
- 当主节点出现故障,此时哨兵节点会通过 Raft 算法实现选举机制,共同选举出一个哨兵节点为leader,来负责处理主节点故障转移的过程和通知,所以整个运行哨兵的集群的数量不得少于3个节点
- 由leader哨兵节点执行故障转移,过程如下:
- 将某一从节点升级成新的主节点,让其他从节点指向新的主节点;
- 若原主节点恢复也变成从节点,并且执行新的主节点
- 通知客户端主节点已经更换 , 需要注意的是客观下线是主节点才具备的概念,从节点和哨兵切点下线后,不会有后续的故障转移操作
redis cluster 集群
集群主要的作用有数据分区和高可用
而数据分区:
- redis 集群引入了哈希槽的概念
- redis集群有 16384个哈希槽
- 集群的每组节点负责一部分哈希槽
- 每一key通过 CRC16 校验后对16384进行取余来决定存放到那个哈希槽,通过这个值来找到对应槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
redis 优化
- 开启 AOF 持久化
- 设置碎片自动清理
- 设置内存数据淘汰策略
- 尽可能使用 HASH 数据类型
- 设置 key 的过期时间
- 部署主从复制 、备份数据、采用哨兵或集群方案的高可用
缓存和数据库 双写一致性问题
先更新数据库,在删除缓存 + 缓存做过期时间,数据过期再有读请求可从数据库直接更新缓存
缓存三大击穿问题
缓存雪崩: 缓存同一时间大面积的过期失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案:
缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。
缓存击穿: 缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。解决方案
设置热点数据永远不过期。
加互斥锁,互斥锁
缓存穿透: 缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案:
接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力
ELK
ELK 的工作原理
- 在所有需要收集日志的服务器上部署 logstash;或者先将日志集中化管理到日志服务器上,然后在日志服务器上部署 Logstash
- logstash 收集日志,将日志格式化输出给 elastisearch 群集中
- elastisearch 对格式化后的数据进行索引和存储
- kibana 从 ES 群集中查询数据生成图表,并进行前端数据的展示
ELK 的插件有哪些
zabbix
Zabbix 组件 及 工作原理
组件: 有 zabbix agent 、zabbix server 、 数据库、 zabbix web 、 zabbix proxy、zabbix java gateway
工作原理: zabbix agent 安装在被监控的主机上,zabbix agent 负责定期收集客户端本地各项数据,并发送至zabbix server端,zabbix server端收到数据后,将数据存储到数据库中,用户基于zabbix web 网页看到数据在前端展示图像。
zabbix 如何自定监控项
明确获取监控指标数值的命令或者脚本
在被监控主机配置文件目录/etc/zabbix/zabbix_agent2.d 中创建.conf 为后缀的监控项配置文件,自定义获取监控指标数值的键值
格式: UserParameter=键值名,获取值得命令/脚本路径
在服务端web 管理页面中一次添加 模板 - 监控项 - 触发器 - 图形
在监控模板与被监控主机相关联
zabbix 你都监控哪些参数
我们主要用的是 zabbix 作为监控,主要监控 数据库、 web、 网络、中间件和一些其他应用,比如我们监控mysql 主要关注磁盘、内存、并发数、数据库的增删改查频率,主从状态等等
- 数据库性能方面,主要关注:
- 查询吞吐量
- 查询执行性能
- 连接情况
- 缓冲池使用情况
- 监控web服务
- web 服务是否正常
- 业务(网页是否能访问、是否可以完成下订单、注册用户)
- 服务的响应时间
- 服务的并发量(活动用户、非活动用户)
- 服务器监控
- 磁盘使用率
- inode 数
- block 数
- 读写速率
- 监控cpu 负载 利用率
- 内存的使用率 交换空间大小
- 监控网卡的速率
- 当前系统的总进程数
kafka
Zookeeper 是什么?
Zookeeper 是一个分布式管理框架,相当于各种分布式应用服务的 注册中心 + 文件系统 + 通知机制
本质:用于注册各种分布式应用,存储和管理各种分布式应用服务的元数据,如果应用服务状态发生改变会通知客户端
Zookeeper 选举机制
第一次启动选举机制:比较服务器节点的myid , 谁myid大就获取比它的小的服务器节点的选票,当选票超过节点服务器数量的半数,则当选为 leader, 其他节点为follower,即使后面再有其他myid 更大的节点加入到集群也不会影响之前的选举结果
非第一次选举:
如果是非 leader 节点故障,替换的新节点继续当 follower , 与 leader对接并同步数据。
如果是 leader 节点挂了,则需要重新选举 新 leader,先比较每个节点的 Epoch (参加选举的次数),当选 leader 。 若Epoch 有相同的节点,则在比较 Zxid (写操作的事务ID ) 选Zxid最大的当选 leader,若Zxid 也有相同的则选择 myid 最大的当选 leader
消息队列的作用
应用解耦、异步处理、流量削峰、缓冲
消息队列的模式
点对对模式: 一对一,消费者消费消息之后会删除消息
发布订阅(观察者模式):一对多,消费者消费消息后不会删除消息
kafka 架构
broke :kafka服务器节点
producer : 生产者,发布消息到 topic
consumer : 消费者
consumer group 消费者组,是消息的实际订阅者,一个消费者组包含一个或多个消费者,组内成员不能重复消费同一个 partition 数据
producer —> topic 消息队列 -----> partition 分区 -----> replica 副本(leader 负责数据读写、follower 只负责同步复制 leader 数据)
consumer —> offset 偏移量 (用来记录消费者上一次消费的位置)
zookeeper 存储 kafka 集群的元数据信息 , 生产者和消费者的动作都需要 zookeeper 的管理和支持,比如生产者推送数据到 kafka 集群 需要通过 zookeeper 去寻找 kafka 服务器节点的位置,消费者需要从 zookeeper 获取 offset 记录的上一次消费的位置 继续往后消费
kafka 只能保证 partition 分区内的消息顺序,消费者无法保证 partition 之间的顺序,如需要严格保证消息的消费顺序(商品秒杀、抢红包)要把 partition 数目设置为1
kafka ACK应答机制保证数据的可靠性
ack 配置参数 0 (效果类似于异步复制,不等待 follower 同步完成即可让生产者发下一条消息)
1 (效果类似于半同步复制,至少等待一个 follower 同步完成才让生产者发下一条消息)
-1 (类似于全同步复制,要等待所有的 follower 同步完成才让生产者发下一条消息)
Ceph
数据存储类型
块存储:一对一,只能被一个主机挂载使用, 数据以块为单位进行存储,典型代表:硬盘
文件存储:一对多,能被多个主机同时挂载/传输使用,数据以文件的形式存储的(元数据和实际数据是分开存储)
对象存储:一对多,能被多个主机/应用通过API 接口访问使用,数据以文件的形式存储,一个文件即一个对象,元数据和实际数据是存储在一起的的,文件是扁平化存储的,没有目录的层级关系,典型代表:OSS S3
Ceph 是一个分布式存储系统,具有高性能、高扩展性、高可用性等特点,还集块/文件/对象存储于一身
Ceph 架构 (从下往上看)
客户端(主机/ 虚拟机 / 容器 / 应用程序):使用存储的
LibRADOS 对象访问接口 (默认的三个接口 RDB 块存储接口 、 CephFS 文件存储接口、 RGW 对象存储接口,还支持用户使用 java /c /python 等编程语言二次开发自定义的接口):提供存储接口给客户端使用的
RADOS 基础存储系统(统一存储池):提供存储能力进行读写的
Ceph 组件
OSD 负责存储数据,一般一个磁盘对应一个 OSD ,响应客户端的读写请求
Monitor(mon) Ceph监视器,负责保存OSD的元数据,维护Ceph集群状态的各种图表视图(监控全局状态),管理客户端的认证与授权
Manager(mgr) 负责跟踪集群状态和监控指标,暴露接口给监控软件获取监控指标数据
MDS 负责保存CephFS文件系统的元数据,仅在使用CephFS接口功能的时候使用
pg 可理解为保存OSD位置的索引,一个pg可以保安多个数据对象,一个数据对象只能属于一个PG
pool 数据池,可以理解为一个命名空间,一个pool里包含多个pg,不同的pool的pg可以重名
Ceph 的存储过程
- 文件默认会被按照 4M 大小进行分片成为一个或多个数据对象
- 每个数据对象都有一个oid(由问及那ID(ino)和分片编号(ono)组成),通过对oid使用hash算法得到一个16进制的数值,再除以pool里的PG总数取余,得到数据对象的pgid
- 通过对pgid使用 CRUSH 算法得到 PG 对应的OSD的ID(如果多副本,则是主从的OSD的ID)
- 将数据对象数据存储到对应的OSD上
第三阶段
Docker
docker 是什么?
docker 是基于go语言开发的一种容器引擎,用来运行容器里的应用,docker用来管理容器和镜像的一种工具。 达到**一次封装,到处运行**font>的目的
docker 容器与 虚拟机的区别?
容器 | 虚拟机 |
---|---|
所有容器共享宿主机内核 | 每个虚拟机都有独立的操作系统和内核 |
使用namespace隔离资源,使用cgroup限制资源的最大使用量 | 完全隔离,每个虚拟机都有独立的硬件资源 |
秒级启动速度 | 秒级启动速度 |
容器相当于宿主机的进程,性能几乎没有损耗 | 需要hypervisor虚拟机管理程序对宿主机资源虚拟访问,至少有20~50%资源损耗 |
单机容量能够支持成百上千个容器 | 单机容量只能支持最多几个虚拟机 |
docker 三大核心概念
- 镜像:是用来创建容器的基础,是一个只读的模板文件,里面包含容器中的应用程序所需要的所有内容(包含程序运行文件、配置文件、运行库文件、运行环境)
- 容器:是用镜像运行的实例,容器可以被创建、启动、停止、删除,每个容器之间默认是相互资源隔离的
- 仓库:用来保存镜像的地方,有共有仓库和私有仓库之分
6大namespace 命名空间是什么?
- mnt 挂载点隔离
- user 用户隔离
- net 网络隔离
- ipc 进程通信隔离
- uts 主机名域名隔离
- pid 进程隔离
docker的镜像和容器管理命令?
镜像操作:
docker search 镜像
docker pull 下载镜像
docker images 查询当前拥有的镜像
docker tag 旧镜像名:旧标签 新镜像:新标签
docker inspect 查看镜像或者容器的详细信息
docker login 登入仓库
docker push 上传镜像到仓库
docker save -o 存储文件名 存储的镜像 将镜像保存为本地文件
docker load < 存储的文件 将镜像导入到镜像库中
容器操作
docker create 【-it】【–name 容器名】 镜像名:标签 创建容器
docker start 启动容器
docker ps 【-a】 查看本地容器
docker stop | kill 停止容器
docker rm 删除容器
docker logs 查看容器日志
docker exec -it 容器名|容器ID bash|sh 进入容器分配一个伪终端,
docker cp 容器名:目录 宿主机本地目录 将容器中的目录复制到宿主机中
docker export -o 容器模板文件 容器名|容器 ID 容器的导出
docker import 模板文件 – 镜像:标签 将容器模板导入成镜像
docker run 创建并启动容器
docker run 的运行过程
- 检查本地是否有镜像文件(如果有则直接使用本地镜像创建容器,如果没有则从仓库拉取镜像再创建文件)
- 在只读的镜像层上挂载一层可读可写的容器层
- 从 docker 网桥 (虚拟交换机) 给容器分配一个虚拟接口和IP 地址
- 使用镜像的默认命令或者指定的命令启动容器,直到容器主进程退出为止
cgroup 资源限制
cpu 限制
#设置单个容器进程能够使用的CPU使用率上限
docker run --cpu-period <单个CPU调度周期时间,值范围1000~1000000> --cpu-quota <容器进程最大使用的CPU时间,值范围>=1000>#设置多个容器的CPU占用的百分比(只能在多个容器同时运行且资源紧张时有效)
docker run --cpu-share <容器进程最大占用的份额,值为1024的倍数>#设置容器绑定指定CPU
docker run --cpuset-cpus <CPUID,如多个CPU用,间隔>
内存限制
#设置容器能够使用的内存和swap的大小
docker run -m <内存大小> --memory-swap=<内存与swap的总大小>
=-1 #不限制swap大小,宿主机有多少则可用多少
=0或不设置 #swap为内存的两倍
=内存的值 #不使用swap
磁盘IO读写限制
docker run --device-read-bps <磁盘设备文件:速率(K M G kb mb gb)> #限制容器在某个磁盘上读的速率
–device-write-bps <磁盘设备文件:速率(K M G kb mb gb)> #限制容器在某个磁盘上写的速率
–device-read-iops <磁盘设备文件:次数> #限制容器在某个磁盘上读的次数
–device-write-iops <磁盘设备文件:次数> #限制容器在某个磁盘上读的次数
docker 网络模式
- host 与宿主机共享网络命名空间,容器和宿主机使用同一个IP、端口范围(容器和宿主机不可以使用相同的端口)等网络资源
- container 与容器共享网络命名空间,两个容器使用同一个IP、端口范围(两个容器不可以使用相同的端口)等网络资源
- none 每个容器都有独立的网络命名空间,但是容器没有eth0网卡、IP、端口等,只有lo网卡
- bridge 默认的网络模式。每个容器都有独立的网络命名空间(net namespace),每个容器有独立的IP、端口范围(每个容器可以使用相同的端口)、路由、iptables规则等
- 自定义网络:可以自定义创建一个网桥和网段,使得可 自定义容器IP 创建 容器c
docker network create --subnet=新IP网段 --opt “com.docker.network.bridge.name”=“新网桥名称” 新网络模式名称
docker run --network=新网络模式名称 --ip 自定义IP 镜像:标签 [启动命令]
dockerfile 有哪些指令
- FROM 指定新镜像所基于的基础镜像
- MAINTAINER 说明新镜像维护人信息
- RUN 执行命令
- ENTRYPOINT 设定容器启动时第一个运行的命令及其参数。
- CMD 启动容器时默认执行的命令或者脚本
- EXPOSE 端口号
- ENV 环境变量
- ADD 将源文件复制到镜像中 拥有压缩的功能
- COPY 复制
- VOLUME 在容器中创建一个挂载点
- USER 指定运行容器时的用户
- WORKDIR 路径
- ONBUILD 为别人做嫁衣 在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
dockerfile 如何缩小构建镜像的体积
使用更加小的基础镜像
将多条RUN 命令用 && 或者 ; 来执行多条命令
可以构建镜像步骤最后添加清空系统和应用程序的缓存命令
使用多阶段构建 FROM 第一简短的基础镜像【AS 别名】
FROM 第二阶段的基础镜像
COPY --from=别名 第一阶段构建的文件/目录 当前阶段的文件/目录
docker-compose 是什么?
docker-compose 用来单机编排
例如:我们现在需要启动10个容器,其中3个nginx,2个redis,3个mysql,1个zabbix,1个ansible,有些容器需求先启动,有容器需要后启动,在启动的时候是有先后顺序的。
这时候需要批量启动容器,而且启动的时候容器之间是有依赖关系,需要考虑启动顺序的
我们可以将编排的内容全部写到一个yaml文件里,docker 的compose根据这个yaml文件里的安排去启动容器。
docker-compose.yml 配置讲解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3yiLRRjG-1692605549638)(C:\Users\li\AppData\Roaming\Typora\typora-user-images\image-20230726161153354.png)]
version**:指定 docker-compose.yml 文件的写法格式
services:多个容器集合environment:环境变量配置,可以用数组或字典两种方式
image:指定服务所使用的镜像
expose:定义容器用到的端口(一般用来标识镜像使用的端口,方便用ports映射)
ports:定义宿主机端口和容器端口的映射,可使用宿主机IP+宿主机端口进行访问宿主机端口:容器端口
注:仅指定容器端口时,宿主机将会随机选择端口
volumes:卷挂载路径,定义宿主机的目录/文件和容器的目录/文件的映射 宿主机路径:容器路径
depend_on: 规定service加载顺序,例如数据库服务需要在后台服务前运行
extra_hosts:类似于docker里的–add-host参数 配置DNS域名解析(域名和IP的映射)
restart: always :配置重启,docker每次启动时会启动该服务
no,默认策略,在容器退出时不重启容器。
on-failure,在容器非正常退出时(退出状态非0),才会重启容器。
on-failure:3,在容器非正常退出时重启容器,最多重启3次。
always,在容器退出时总是重启容器。
unless-stopped,在容器退出时总是重启容器,但是不考虑在 Docker 守护进程启动时就已经停止了的容器。privileged: true :开启特权模式
ser: root :指定容器运行的用户名
links:将指定容器连接到当前连接,可以设置别名,已废弃,推荐使用networks
networks:
logging:日志服务
driver:默认json-file,可选syslog
network_mode:设置网络模式
bridge:默认,需要单独配置ports映射主机port和服务的port,并且开启了容器间通信
host:和宿主机共享网络,比如service是8081端口,无需配置ports,直接可以用主机IP:8081访问
cap_add cap_drop:赋予/删除 容器某些能力
可运行 man 7 capabilities 查看所有能力
build:配置构建时,Compose 会利用它自动构建镜像,该值可以是一个路径,也可以是一个对象,用于指定 Dockerfile 路径
注:如果指定build同时也指定image,那么会从build里构建,镜像的名字和tag将取image指定的
command:覆盖容器启动后默认执行的命令
docker-compose up -d(相当于 build + start) :构建(容器)并启动(容器)整个project的所有service
docker-compose down -v(相当于 stop + rm ) :停止并移除整个project的所有services
Harbor 私有仓库管理
consul 服务自动发现
registrator:发现应用的网络位置,发送给consul server/client的自动发现模板进行注册
consul server : 收集自动发现的信息,将所有需要注册的信息持久化到本地,可以通过server-leader将注册信息同步给其他server节点,以及对各个server节点做健康检查
consul template:基础consul的注册信息自动根据配置文件模板生成配置文件并替换,最后代理服务器则根据consul template 生成的配置进行代理转发
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LrjFfcfA-1692605549638)(C:\Users\li\AppData\Roaming\Typora\typora-user-images\image-20230727071442218.png)]
https 的工作流程
- 服务端会事先通过 CA 签发证书和私钥
- 客户端发送 https 请求到服务端的 443 端口
- 服务端发送包含公钥、证书有效期及 CA 机构等信息的证书给客户端
- 客户端会先通过 CA 验证证书的有效性
- 若证书有效,客户端会在本地随机生成会话密钥并通过服务端发来的公钥加密后返回给服务端
- 服务端再通过私钥进行解密得到会话密钥,之后双方即可使用会话密钥加密/解密来实现密文通信
数据库是否放在容器中运行?为什么?
mysql 也不是全然不能容器化
- 对数据丢失不敏感的业务就可以数据化,利用数据库分片来增加实例数,从而增加吞吐量
- docker 适合跑轻量级或分布式数据库,当docker 服务挂掉,会自动启动新容器,而部署继续重启容器服务
- 数据库利用中间件和容器化系统能够自动伸缩、容灾、切换、自带多个节点的也可以进行容器化
docker容器的重启策略?
no: 默认策略,再重启退出时不重启容器
on-failure: 在容器非正常退出时(退出状态非0),才会重启容器
on-failure:3 在容器非正常退出时重启容器,最多重启3次
always: 在容器退出时总是重启容器
unless-stopped: 在容器退出时总是重启容器,但不考虑守护进程启动时已经停止的容器
Ansible
Ansible 概念
ansible 自动化运维工具 (机器管理工具) 可以实现批量管理多台(成百上千)的主机,应用级别的跨主机编排工具
特性:
无 agent 的存在,不需要在被控制节点上安装客户端应用
通过ssh协议与被控制节点通信
基于模块工作的,可以通过模块实现在被控制节点上执行命令操作
很多模块具有幂等性,可以实现多次模块操作的状态如果没有发送改变,则不会重复执行
模块
command 在远程主机执行 Linux 命令 ,但不支持管道、重定向符号,ansible 的默认模块
shell 在远程主机执行 Linux命令 支持管道、重定向
cron 在远程主机设置 crontabl 计划性任务
user 在远程主机管理用户 账户
group 在远程主机管理组用户
copy 将本地文件/目录/内容 复制到远程主机中
file 在远程主机管理文件属性
ping 检测与远程主机连通性
hostname 在远程主机设置主机名
mount 在远程主机挂载目录/设备文件
yum 在远程主机通过yum 安装软件
service/systemd 管理远程主机上的管理服务的运行状态
scrpit 在远程主机执行本地的脚本
archive 在远程主机压缩文件
unarchive 在本地或远程主机的压缩包在远程主机解压缩
replace 在远程主机修改文件内容
setup 获取远程主机的 facts 信息
格式: ansible 组名 -m 模块 -a 参数
K8S
k8s 有哪些组件
k8s 有 master 和 worker node 两大类节点
master节点有 apiserver 、 controller-manager 、 scheduler 以及使用 etcd 做 k8s 集群的数据库
node 节点有 kubelet 、 kube-proxy 容器引擎
k8s 组件的作用
apiserver : 所有服务请求的统一访问入口
contorller-manager : 控制器管理器,负责管理为 POD 副本集、命名空间、端点等资源以及部署的控制器,通过apiserver 监控整个集群状态,并确保集群处于预期的工作状态
scheduler: 资源调度器,负责 POD 资源的调度,通过调度算法(预选策略、优选策略)为部署的 POD 选择最合适的 node 节点
etcd: k8s 集群的数据库,是一种键值对存储的分布式数据库,负责存储 k8s 集群的所有的重要信息,只有 apiserver 有读写权限。
kubelet: 接收master发来的请求,创建和管理 POD 和容器,跟容器引擎交互实现容器的生命周期的管理:收集 node 节点资源信息和pod运行状态汇报给master的apiserver
kube-proxy: 作为server资源的载体,实现pod网络代理,可以维护网络规则和四层负载均衡工作
容器引擎/容器运行时: 运行容器用的
pod 的创建过程
- 用户通过客户端发送创建pod 的请求到master节点上的 apiserver,
- apiserver 会先请求信息写入etcd中进行保存,再寻找contorller-manager 根据预设的资源配置模板创建 pod 资源
- 然后contorller-manager 会通过 apiserver 去找 scheduler 为新创建的 pod 选择最合适的 node 节点
- scheduler 会通过调度算法的预选策略和优选策略筛选出最合适的node节点进行调度
- 然后再通过apiserver 找到 对应的 node 节点上的 kubelet 去创建和管理 pod
- kubelet 会跟容器引擎进行交互来管理pod 和容器的生命周期
- 用户还可通过apiserver 在kube-proxy上写入网络规则,创建service资源,实现对pod 的服务发现与负载均衡。
K8s 资源对象
pod : 是K8S 能够创建和管理的最小单元,一个pod 里可以包含一个或多个应用容器,pod里的容器之间共享 网络、存储等资源
pod 控制器:
deployment:部署无状态应用,同时负责管理 replicaset (维持pod的副本期望数量)和 pod (一个容器化的应用进程)
statefulset: 部署有状态应用
daemonset: 在所有的 node 节点上部署同一种 pod
job: 一次性部署短期任务的 pod,pod执行完任务就自动退出
cronjob: 周期性部署短期任务的 pod
K8S 二进制搭建
1)etcd集群
使用cfssl签发证书和私钥
解压etcd软件包,获取二进制文件 etcd etcdctl
准备etcd集群配置文件
启动etcd服务进程,加入到etcd集群
2)master
使用cfssl签发证书和私钥
准备bootstrap-token认证文件
解压服务端软件包,获取二进制文件 kube-apiserver kube-controller-manager kube-scheduler kubectl
准备apiserver、controller-manager、scheduler的服务启动参数配置文件
准备controller-manager、scheduler、kubectl的 kubeconfig 集群配置文件(加入K8S集群的引导文件)
依次启动apiserver、controller-manager、scheduler服务进程
3)node
获取二进制文件 kubelet kube-proxy
准备 kube-proxy、kubelet 的 kubeconfig 集群配置文件 kube-proxy.kubeconfig bootstrap.kubeconfig(kubelet初次访问apiserver加入集群的引导文件)
准备 kubelet、kube-proxy 的服务启动参数配置文件
启动 kubelet 服务进程,发起 csr 请求证书,master 通过 csr 请求,颁发证书给 kubelet
加载 ipvs 模块,启动 kube-proxy 服务进程
安装 CNI 网络插件(flannel、calico等),CoreDNS
4)多 master 高可用
复制 master 的 k8s 相关的 证书、配置文件、二进制文件 和 etcd 的证书
修改 配置文件启动参数 启动 master 组件(apiserver、controller-manager、scheduler)的服务进程
部署 负载均衡器 和 keepalived 高可用
修改 node 组件(kubelet、kube-proxy)和 kubectl 的 kubeconfig 配置文件中的 server 参数地址为 VIP
K8S kubeadm搭建
kubeadm init:在使用kubeadm方式安装K8S集群时,可根据初始化配置文件或者配置参数快速的初始化生成一个K8S的master管理平台
kubeadm join:根据kubeadm init初始化的提示信息快速的将一个节点作为node节点或者其它的master节点加入到K8S集群当中
1)所有节点进行初始化,安装docker引擎和kubeadm kubelet kubectl
2)生成集群初始化配置文件并进行修改
3)使用kubeadm init根据初始化配置文件生成K8S的master控制管理节点
4)安装CNI网络插件(flannel、calico等)
5)在其他节点使用kubeadm join将节点以node或者master角色加入K8S集群
kubeadm 部署的K8S集群更新证书
1)备份老证书和kubeconfig配置文件
mkdir /etc/kubernetes.bak
cp -r /etc/kubernetes/pki/ /etc/kubernetes.bak
cp /etc/kubernetes/*.conf /etc/kubernetes.bak
2)重新生成证书
kubeadm alpha certs renew all --config=kubeadm.yaml
3)重新生成kubeconfig配置文件
kubeadm init phase kubeconfig all --config kubeadm.yaml
4)重启kubelet和其他K8S组件的Pod容器
systemctl restart kubelet
mv /etc/kubernetes/manifests /tmp
mv /tmp/*.yaml /etc/kubernetes/manifests
K8S 3种网络
节点网络 Node节点网卡的IP nodeIP
Pod网络 podIP
Service网络 clusterIP
K8S 3种接口
CRI 容器运行时接口 docker containerd podman cri-0
CNI 容器网络接口 flannel calico cilium
CSI 容器存储接口 ceph nfs gfs s3
flannel 3种模式
UDP 出现最早,性能较差,基于flanneld应用程序实现数据包的封装/解封装
VXLAN 默认模式,推荐使用的模式,性能比UDP模式更好,基于内核实现数据包的封装/解封装
Host-gw 性能最好,但是配置复杂,不能跨网段
flannel UDP模式工作原理
1)应用数据包从源主机的Pod容器发出到cni0网桥接口,再由cni0转发到flannel0虚拟接口
2)flanneld服务会监听flannel0接口接收到的数据,flanneld服务会将内部数据包封装到UDP报文里
3)flanneld会根据在etcd中维护的路由表查到目标Pod所在的Node节点IP,在UDP报文外再封装Node节点IP报文、MAC报文后,通过物理网卡发送到目标Node节点
4)UDP报文通过8285号端口送到目标主机的flanneld进程进行解封装,再通过flannel0接口转发到cni0网桥,然后通过cni0网桥转发到目标Pod容器
flannel VXLAN模式工作原理
1)原始数据帧从源主机的Pod容器发出到cni0网桥接口,再由cni0转发到flannel.1虚拟接口
2)flannel.1接口接收到数据帧后添加VXLAN头部,在内核封装成UDP报文
3)flanneld会根据在etcd维护的路由表通过物理网卡发送到目标Node节点
4)UDP报文通过8472号端口送到目标主机的flannel.1接口在内核进行解封装,然后将原始报文通过cni0网桥转发到目标Pod容器
Calico IPIP模式工作原理
1)源Pod容器发出的原始数据IP包通过内核的IPIP驱动直接封装到宿主机网络的IP包中
2)根据tunl0接口的路由通过物理网卡发送到目标Node节点
3)数据包到达目标节点后再通过IPIP驱动解包得到原始数据IP包
4)然后通过路由规则发送给 veth pair 设备到达目标Pod容器
Calico BGP模式工作原理(本质就是通过路由表来维护每个 Pod 的通信)
1)源Pod容器发出的原始数据IP包会通过 veth pair 设备到达宿主机网络空间
2)然后根据原始数据IP包的目标IP和宿主机的路由规则,找到目标Node节点的IP,再通过物理网卡发送到目标Node节点
3)根据目标Node节点的路由规则,直接通过目标Pod容器的 veth pair 设备发送到目标Pod容器
flannel 和 calico 区别?
flannel: UDP VXLAN Host-gw
默认网段:10.244.0.0/16
通常使用VXLAN模式,采用的是叠加网络、IP隧道方式传输数据,对性能有一定的影响
功能简单配置方便利于管理,但是不具备复杂的网络策略规则配置能力
calico: IPIP BGP 混合模式(CrossSubnet)
默认网段:192.168.0.0/16
使用IPIP模式可以实现跨子网传输,但是传输过程中需要封包和解包,对性能有一定的影响
使用BPG模式,把Node节点看作成路由器,根据Felix、BIRD分发和维护的路由规则,可直接实现BGP路由转发,传输过程中不需要封包和解包,因此性能较好,但只能在同一个网段内使用,无法跨子网传输
具有更丰富的网络策略配置管理能力、性能更好、功能更全面,但是维护起来较为复杂
所以对于较小规模且网络要求简单的K8S集群,可以采用flannel。对于集群规模较大且要求更多的网络策略配置时,可以采用性能更好、功能全全面的calico
陈述式资源管理
kubectl create <资源类型> <资源名称> -n 命名空间 [选项]
–image=镜像 --replicas=副本数 --port=容器端口
kubectl get <资源类型|all> [资源名称] -n 命名空间 -o wide|yaml|json -w
kubectl describe <资源类型> <资源名称> -n 命名空间
kubectl delete <资源类型> <资源名称>|–all -n 命名空间 [–force --grace-period=0]
立即终止Pod运行,强制删除资源
kubectl exec -it -n 命名空间 <Pod资源名称> [-c 容器名称] sh|bash
kubectl logs -n 命名空间 <Pod资源名称> [-c 容器名称] [-p]
kubectl scale -n 命名空间 deployment <资源名称> --replicas=副本数
kubectl expose -n 命名空间 deployment <资源名称> --name <自定义svc资源名称> --port <clusterIP的端口> --target-port <容器的端口> --type <svc的类型>
kubectl create svc <svc资源类型> <资源名称> --tcp=<clusterIP的端口>:<容器的端口>
kubectl set image deployment <资源名称> <容器名>=<镜像名>
kubectl rollout history deployment <资源名称>
kubectl rollout undo deployment <资源名称> [–to-revision= ]
kubectl rollout status deployment <资源名称>
service 的 4 种类型:
ClusterIP:默认的service资源的类型,提供clusterIP供K8S集群内部访问
NodePort:会在每个Node节点上开启一个端口,K8S集群内部和外部的用户都可以通过NodeIP:NodePort访问service以及其关联的Pod
LoadBalancer:使用公有云的LB服务和service做映射,用户可以使用公有云LB服务的IP地址即可将请求转发到Node节点,再通过NodeIP:NodePort访问service以及其关联的Pod
ExternalName:相当于给一个域名或IP做别名,Pod可以通过这个service访问相关的外部服务
service 的端口:
port :service 资源的 clusterIP 所使用的端口
nodePort :在NodePort类型的service所定义的,在每个Node节点上开启的端口(默认范围为30000~32767)
targetPort :service 将发送给 port 或 nodePort 的请求转发到后端的 Pod 的容器端口
containerPort :创建 Pod 时所指定的容器端口
K8S集群内部 http://clusterIP:port --> podIP:containerPort
K8S集群外部 http://nodeIP:nodePort --> podIP:containerPort
如何获取资源配置清单文件模板(yaml配置文件)
1)手撕yaml配置文件,可根据 kubectl explain 命令获取字段信息
2)无中生有的方式:kubectl create|run|expose … --dry-run=client -o yaml > XXX.yaml
3)查看已存在的资源配置方式:kubectl get <资源类型> <资源名称> -n 命令空间 -oyaml > XXX.yaml
kubectl edit <资源类型> <资源名称> 手动复制资源配置,再粘贴到文件中
4)复制官方文档的资源配置案例
一个pod能包含几个容器?
1个 pause容器(基础容器/父容器/根容器)
1个或多个应用容器(业务容器)
通常一个Pod最好只包含一个应用容器,一个应用容器最好只运行一个业务进程
同一个Pod里的容器,都是运行在同一个Node节点上的,并且共享 NET MNT UTS IPC PID 命名空间
pause容器的作用?
是作为共享 NET MNT UTS IPC PID 命名空间的基础
给Pod里的其它容器提供网络、存储资源的共享
作为PID=1的进程(init进程)管理整个Pod容器组的生命周期
Pod 的 3 种类型:
- 控制器管理的Pod:由scheduler进行调度的;被控制器管理的;有自愈能力,一旦Pod挂掉了,会被重新拉起;有副本管理、滚动更新等功能
- 自主式Pod:由scheduler进行调度的;不被控制器管理;没有自愈能力,一旦Pod挂掉了,不会被重新拉起;没有副本管理、滚动更新等功能
- 静态Pod:不由scheduler调度的,而是由kubelet自行管理的;始终与kubelet运行在同一个Node节点上,不能被直接删除
静态Pod资源配置文件默认放置在/etc/kubernetes/manifests目录中,当此目录中有Pod资源配置文件存在或者消失时kubelet会自动创建或删除静态Pod
Pod 的 3 种容器:
-
pause容器(基础容器/父容器/根容器):给Pod的容器组作环境初始化,具体见上
-
init容器(初始化容器/init container):可以为应用容器事先提供运行环境或辅助工具;还可以阻塞或延迟应用容器的启动
如果Pod有多个init容器时,是串行启动,要在上一个init容器成功的完成启动、运行和退出后才会启动下一个init容器 -
应用容器(业务容器/main container):提供应用程序业务
如果Pod有多个应用容器时,默认是并行启动的,应用容器要在所有init容器都成功的完成启动、运行和退出后才会启动
Pod 的 3 种镜像拉取策略: spec.containers.imagePullPolicy
- IfNotPresent:优先使用本地已存在的镜像,如果本地没有则从仓库拉取镜像。是标签为非latest的镜像的默认镜像拉取策略
- Always:总是从仓库拉取镜像,无论本地是否已存在镜像。是标签为latest或无标签的镜像的默认镜像拉取策略
- Never:仅使用本地镜像,总是不从仓库拉取镜像
Pod 的 3 种容器重启策略: spec.restartPolicy
- Always:当Pod中的容器退出时,总是重启容器,无论容器退出状态码如何。是默认的容器重启策略
- OnFailure:当Pod中的容器异常退出时(容器退出状态码为非0),才会重启容器;正常退出的容器(容器退出状态码为0)不会重启
- Never:当Pod中的容器退出时,总是不重启容器,无论容器退出状态码如何。
Pod 容器的资源限制
spec.containers.resources.requests.cpu|memory 设置Pod容器创建时需要预留的资源量 容器应用最低配置 <= requests <= limits
spec.containers.resources.limits.cpu|memory 设置Pod容器能够使用的资源量上限,如果容器进程内存使用量超过limits.memory会引发OOM
CPU资源量单位: cpu个数 1 2 0.1 0.5 0.25 毫核 100m 250m 1000m 1500m
内存资源量单位:整数(默认单位为字节) 2的底数单位(Ki Mi Gi Ti) 10的底数单位(K M G T)
kubectl describe -n 命名空间 pod <pod名称> 查看Pod中每个容器的资源量限制
kubectl describe node <node名称> 查看Node节点中的每个Pod或总的资源限制使用情况
Pod 容器的 3 种探针(健康检查)
存活探针(livenessProbe):探测是否正常运行。如果探测失败则kubelet杀掉容器(Pod容器会根据重启策略决定是否重启)
就绪探针(readinessProbe):探测Pod是否进入就绪状态(ready状态栏1/1),并做好接收service请求的准备。如果探测失败则Pod会变成未就绪状态(ready状态栏0/1),service资源会删除所关联的端点(endpoints),并不再转发请求给就绪探测失败的Pod
启动探针(startupProbe):探测容器内的应用是否启动成功。在启动探针探测成功之前,存活探针和就绪探针都会暂时处于禁用状态,直到启动探针探测成功
探针的 3 种探测方式
exec:在command字段中指定在容器内执行的Linux命令来进行探测,如果命令返回码为0则认为探测成功,如果返回码为非0则认为探测失败
tcpSocket:向指定的Pod容器端口发送tcp连接请求,如果端口正确且tcp连接成功则认为探测成功,如果tcp连接失败则认为探测失败
httpGet:向指定的Pod容器端口和URL路径发送http get请求,如果http响应状态码为2XX 3XX则认为探测成功,如果响应状态码为4XX 5XX则认为探测失败
探针参数:
initialDelaySeconds:指定容器启动后延迟几秒开始探测
periodSeconds:每天探测的间隔时间(秒数)
failureThreshold:探测连续失败几次后判断探测失败
timeoutSeconds:指定探测超时等待时间(秒数)
Pod 应用容器生命周期的启动动作和退出动作
spec.containers.lifecycle.postStart 配置子字段 exec.command 设置 Pod 容器启动时额外的命令操作
spec.containers.lifecycle.preStop 配置子字段 exec.command 设置 Pod 容器运行中被kubelet杀掉退出时所执行的命令操作(不包含容器自行退出的情况)
K8S是通过 List-Watch 机制实现每个组件的协作
controller-manager、scheduler、kubelet 通过 List-Watch 机制监听 apiserver 发出的事件,apiserver 通过 List-Watch 机制监听 etcd 发出的事件
scheduler 的调度策略
预选策略/预算策略:通过调度算法过滤掉不满足条件的Node节点,如果没有满足条件的Node节点,Pod会处于Pending状态,直到有符合条件的Node节点出现
PodFitsResources、PodFitsHost、PodFitsHostPorts、PodSelectorMatches、NoDiskConflict
优选策略:根据优先级选项为满足预选策略条件的Node节点进行优先级权重排序,最终选择优先级最高的Node节点来调度Pod
LeastRequestedPriority、BalancedResourceAllocation、ImageLocalityPriority
Pod 调度到指定的 Node节点
1)使用 nodeName 字段指定 Node节点名称
2)使用 nodeSelector 指定 Node节点的标签
3)使用 节点/Pod 亲和性
4)使用 污点+容忍
标签的管理操作
kubectl label <资源类型> <资源名称> 标签key=标签value
kubectl label <资源类型> <资源名称> 标签key=标签value --overwrite
kubectl label <资源类型> <资源名称> 标签key-
kubectl get <资源类型> <资源名称> --show-labels
kubectl get <资源类型> -l 标签key[=标签value]
亲和性
节点亲和性(nodeAffinity):匹配指定的Node节点标签,将要部署的Pod调度到满足条件的Node节点上
Pod亲和性(podAffinity):匹配指定的Pod标签,将要部署的Pod调度到与指定Pod所在的Node节点处于 同一个拓扑域 的Node节点上
Pod反亲和性(podAntiAffinity):匹配指定的Pod标签,将要部署的Pod调度到与指定Pod所在的Node节点处于 不同的拓扑域 的Node节点上
如何判断是否在同一个拓扑域?
看拓扑域key(topologyKey),如果有其它Node节点拥有与指定Pod所在的Node节点相同的 拓扑域key的标签key和value,那么它们就在同一个拓扑域
亲和性的策略
硬策略(required…):要强制性的满足指定条件,如果没有满足条件的Node节点,Pod会处于Pending状态,直到有符合条件的Node节点出现
软策略(preferred…):非强制性的,会优先选择满足条件的Node节点调度,即使没有满足条件的Node节点,Pod依然会完成调度
污点 taint
kubectl taint node <node名称> key=value:effect
NoSchedule(一定不会被调度) PreferNoSchedule(尽量不被调度) NoExecute(不会被调度,并驱逐节点上的Pod)
kubectl taint node <node名称> key[=value:effect]-
kubectl describe nodes <node名称> | grep Taints
容忍 tolerations
spec:
tolerations:
- key: 污点键名
operator: Equal|Exists
value: 污点键值
effect: NoSchedule|PreferNoSchedule|NoExecute
不可调度
kubectl cordon <node名称>
kubectl uncordon <node名称>
不可调度 + 驱逐
kubectl drain <node名称> --ignore-daemonsets --delete-emptydir-data --force
Pod 的启动过程:
1)通过 scheduler 根据调度算法选择一台在最适合的 Node节点运行 Pod
2)拉取镜像
3)挂载 存储卷 等
4)创建并运行容器
5)根据容器的探针探测结果设置 Pod 状态
Pod 生命周期的 5 种状态
pending: Pod已经创建,但是处于包括Pod还未完成调度到Node节点的过程或者处于镜像拉取过程中、存储卷挂载失败等情况
running : Pod中至少有一个容器正在运行
succeeded: Pod中的所有容器都已经成功退出,且不再重启。(Completed)
failed: Pod中的所有容器都已终止,且至少有一个容器异常退出。(Error)
unknown: Master节点的 controller-manager 无法获取 Pod 的状态,通常是因为 Master节点与 Pod 所在的 Node 节点通信失联导致的
Pod遵循预定义的生命周期,起始于Pending阶段,如果至少其中有一个主要容器正常启动,则进入Running阶段,之后取决于Pod中是否有容器以失败状态结束而进入Succeeded或者Failed阶段。
K8S 中的排障手段
kubectl get pods 查看Pod运行状态
kubectl describe <资源类型|pods> <资源名称> 查看资源的详细信息和事件
kubectl logs <pod名称> [-c <容器名>] [-p] 查看容器的进程日志
kubectl exec -it <pod名称> [-c <容器名>] sh|bash 进入Pod容器,查看容器内部相关状态信息
kubectl debug -it <pod名称> --image=<临时容器的镜像名> --target=<目标容器> 在Pod中创建临时容器进入目标容器进行调试
在Pod容器的宿主机使用nsenter转换网络等命名空间,直接在宿主机进入目标容器的命名空间进行调试
kubectl get nodes 查看Node节点的运行状态
kubectl get cs 查看Master组件的状态
kubectl cluster-info 查看集群信息
journalctl -u kubelet -f 跟踪查看Kubelet进程日志
K8S 的 存储卷 volumes
emptyDir:可实现Pod中的容器之间共享目录数据,但emptyDir存储卷没有持久化数据的能力,存储卷会随着Pod生命周期结束而一起删除
hostPath:将Node节点上的目录/文件挂载到Pod容器的指定目录中,有持久化数据的能力,但只能在单个Node节点上持久化数据,不能实现跨Node节点的Pod共享数据
nfs:使用NFS服务将存储卷挂载到Pod容器的指定目录中,有持久化数据的能力,且也能实现跨Node节点的Pod共享数据
PV PVC
PV:K8S在指定存储设备空间中逻辑划分创建的可持久化的存储资源对象
PVC:是对PV资源对象的请求和绑定,也是Pod能挂载使用的一种存储卷类型
创建 PV 的方式(PV的类型):
手动根据配置文件创建的静态PV
通过StorageClass调用存储卷插件创建的动态PV
PV 的 4 种状态:
Available(可用):表示可用状态,PV 被创建出来了,还未被 PVC 绑定
Bound(已绑定):表示 PV 已经被 PVC 绑定,PV 与 PVC 是一对一的绑定关系
Released(已释放):表示 PVC 被删除,但是 PV 资源还未被回收
Failed(失败):表示 PV 自动回收失败
创建使用 静态PV
1)准备好存储设备和共享目录
2)手动创建PV资源,配置 存储卷类型 访问模式(RWO RWX ROX RWOP) 存储空间大小 回收策略(Retain Recycle Delete)等
3)创建PVC资源,配置请求PV资源的访问模式(必要条件,必须是PV能支持的访问模式) 存储空间大小(默认就近选择大于等于指定大小的PV)来绑定PV
4)创建Pod和Pod控制器资源挂载PVC存储卷,配置存储卷类型为 persistentVolumeClaim ,并在容器配置中定义存储卷挂载点目录
创建使用 动态PV
1)准备好存储设备和共享目录
2)如果是外置存储卷插件,需要先创建serviceaccount账户(Pod使用的账户)和做RBAC授权(创建角色授予相关资源对象的操作权限,再将账户和角色进行绑定),使serviceaccount账户具有对PV PVC StorageClass等资源的操作权限
3)创建外置存储卷插件provisioner的Pod,配置中使用serviceaccount账户作为Pod的用户,并设置相关环境变量参数
4)创建StorageClass(SC)资源,配置中引用存储卷插件的插件名称(PROVISIONER_NAME)
---------------- 以上操作是一劳永逸的,以后只需要创建PVC时设置StorageClass就可以自动调用存储卷插件动态生成PV资源 ----------------
5)创建PVC资源,配置中设置 StorageClass资源名称 访问模式 存储空间大小。创建PVC资源会自动创建相关的PV资源。
6)创建Pod资源挂载PVC存储卷,配置存储卷类型为 persistentVolumeClaim ,并在容器配置中定义存储卷挂载点目录
pod的 5 种控制器:
1)Deployment
部署无状态应用
负责创建和管理 ReplicaSet,维护 Pod 副本数量与期望值相同
负责创建和删除 Pod 资源,多个 Pod 副本时是并行执行的,升级策略默认为滚动更新的方式
2)DaemonSet
部署无状态应用
理论上可以在 K8S 所有 Node 节点上创建相同的 Pod 资源,无论 Node 节点什么时候加入到 K8S 集群(需要考虑到污点和cordon不可调度的影响)
在 DaemonSet 资源清单配置中不需要设置 Pod 副本数(replicas)
3)StatefulSet
部署有状态应用
每个 Pod 名称都是唯一且固定不变的
每个 Pod 都可以有自己专属的持久化存储(基于PVC模板 volumeClaimTemplates 绑定PV实现的)
需要提前创建一个 Headless Service 资源(无头服务,ClusterIP可以为None),并在 StatefulSet 资源清单配置中使用 serviceName 字段关联 Headless Service
可以在 Pod 内通过 <Pod名称>.<svc名称>.<命名空间>[.svc.cluster.local] 格式解析出 PodIP。(基于 Headless Service 和 CoreDNS 实现的)
创建、滚动升级、扩容、缩容 Pod 都是有序进行的(默认为串行执行的,基于字段 .spec.podManagementPolicy: OrderedReady 实现的;字段值若设置为 Parallel,则为并行执行)
创建、扩容 是升序执行的(顺序为 Pod 标识号从 0 到 n-1)
滚动升级、缩容 是倒序执行的(顺序为 Pod 标识号从 n-1 到 0)
Service 资源的类型: 4个常规类型 + 1个特殊类型
ClusterIP NodePort LoadBalancer ExternalName + Headless Service
4)Job
部署一次性的短期任务的Pod资源,Pod不会持久运行
任务正常完成后Pod容器会正常退出并不会再重启(restartPolicy需要设置为Never或OnFailure),且也不会重建Pod
如果任务执行异常导致Pod容器异常退出,会重建Pod重试任务,重试次数受 backoffLimit 字段配置影响(默认为任务失败后重试6次)
5)CronJob
部署周期性的短期任务的Pod资源,Pod不会持久运行
任务正常完成后Pod容器会正常退出并不会再重启(restartPolicy需要设置为Never或OnFailure),且也不会重建Pod
使用必配字段 schedule 设置任务执行的周期表,格式为 “分 时 日 月 周”
有状态服务和无状态服务的区别
有状态:
1. 有实时的数据需要存储
2. 集群服务中,把某一台服务器抽离出去,过一段时间再假如集群中,如果服务集群无法正常工作(相互之间需要数据同步)
无状态:
1. 没有实时的数据需要存储
2. 集群服务中,把某一台服务器抽离出去,过一段时间再加入集群中,如果集群还是正常工作(相互之间不需要同步数据)
configmap
ConfigMap 资源 简称 cm 用于保存 配置文件 环境变量 命令行参数 之类的不需要加密的信息
创建 cm资源
kubectl create cm <资源名称> --from-file=文件|目录 --from-literal=<键名>=<键值>
查看 cm资源
kubectl get cm <资源名称> -o yaml 或 kubectl describe cm <资源名称>
使用 cm资源
挂载的方式:
在 Pod 资源配置中的 spec.volumes 字段设置 configMap 类型的存储卷
在容器配置中用volumeMounts将卷挂载到容器的挂载点目录上,cm资源数据的键名会作为文件名,cm资源数据的键值会作为文件内容(以目录形式挂载的cm卷支持热更新)
在容器配置中用volumeMounts.subPath指定文件名,可实现将卷挂载到容器的文件上(以文件形式挂载的cm卷不支持热更新)
容器环境变量引用的方式:(不支持热更新)
在容器配置中用 env.name 字段自定义容器的环境变量名,在 env.valueFrom.configMapKeyRef.name/key 字段指定自定义的变量的值从哪个 cm资源 的 键 获取 值
在容器配置中用 envFrom.configMapRef.name 字段指定 cm资源的名称,使得 cm资源的 键 和 值 作为容器的环境变量名和环境变量的值
Secret 资源 用于保存密码文件、tls证书/私钥文件、token令牌字符串、镜像私有仓库认证信息 等需要加密的敏感的信息
Secret资源的 4 种类型:
Opaque:默认的Secret资源类型,可以通过选项引用文件、目录、键值对的方式创建Secret资源,并且资源数据的键值会自动转换成base64编码格式
kubernetes.io/tls:用于存储 tls 证书和私钥文件的信息
kubernetes.io/dockerconfigjson:用于存储K8S从harbor等镜像私有仓库拉取镜像时做认证的信息
kubernetes.io/service-account-token:当创建serviceaccount账户资源后K8S会自动创建相关的Secret资源,当Pod访问apiserver时需要使用此Secret资源做认证
创建 Secret资源
kubectl create secret generic|tls|docker-registry <资源名称> 选项
generic <资源名称> --from-file=文件|目录 --from-literal=<键名>=<键值>
tls <资源名称> --cert=证书文件路径 --key=私有文件路径
docker-registry <资源名称> --docker-server=私有仓库URL地址 --docker-username=用户名 --docker-password=密码 --docker-email=邮箱
使用 Secret资源
挂载的方式:
在 Pod 资源配置中的 spec.volumes 字段设置 secret 类型的存储卷
在容器配置中用volumeMounts将卷挂载到容器的挂载点目录上,Secret资源数据的键名会作为文件名,Secret资源数据的键值会作为文件内容
容器环境变量引用的方式:
在容器配置中用 env.name 字段自定义容器的环境变量名,在 env.valueFrom.secretKeyRef.name/key 字段指定自定义的变量的值从哪个 Secret资源 的 键 获取 值
在容器配置中用 envFrom.secretRef.name 字段指定 Secret资源的名称,使得 Secret资源的 键 和 值 作为容器的环境变量名和环境变量的值
陈述式管理资源的方式 修改或添加 资源对象的配置
kubectl patch deployment myapp-demo1 --patch '{"第一层字段": {"第二层字段": {...}}}'
kubectl patch deployment myapp-demo1 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "myapp", "image": "soscscs/myapp:v2"}]}}}}'
K8S集群外的客户端应用访问K8S集群内部服务的方案
service:NodePort LoadBalancer externalIPs 只支持四层反向代理,端口数量有限,如果业务服务应用很多时端口的管理成本会比较高
ingress:支持七层反向代理,可自定义规则根据用户请求的 域名 或 URL路径 转发给指定的 service
ingress 的组成:
ingress资源对象:设置转发规则,告诉 ingress控制器应该根据什么域名或URL路径转发给相应的 service 资源
ingress控制器(ingress-controller):根据 ingress 资源配置的转发规则转发用户请求的组件,以 Pod 形式运行的
ingress 的使用:
DaemonSet + Host网络模式 部署 ingress-controller
数据流向:
客户端 -> 防火墙、前端负载均衡器 -> Node节点的80/443端口进入ingress-controller -> 根据转发规则 -> 业务Pod的service -> 业务Pod
Deployment + NodePort/LoadBalancer类型的service 部署 ingress-controller
数据流向:
客户端 -> 防火墙、前端负载均衡器 -> ingress-controller的service(NodeIP:NodePort)-> ingress-controller -> 根据转发规则 -> 业务Pod的service -> 业务Pod
ingress 的配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: 资源名称
spec:
ingressClassName: ingress控制器类型
rules:
- host: 目标域名(可以精确匹配或通配符匹配,比如 *.kgc.com 可以匹配www.kgc.com或mail.kgc.com等,但不能匹配ky22.www.kgc.com)
http:
paths:
- path: 目标域名后的URL路径(比如 / 代表网页根路径,或者 /test)
pathType: Prefix|Exact(Exact用于精确匹配URL路径;Prefix用于前缀匹配,且只能匹配完整的字符串,/abc能匹配/abc/123,但不能匹配/abc123)
backend:
service:
name: 目标service资源的名称
port:
number: 目标service的端口
- path: URL路径2
....
- host: 域名2
http:
....
基于 https 代理转发
1)先获取 tls 证书和私钥文件
2)创建 tls 类型的 Secret资源 kubectl create secret tls <资源名称> --cert=证书文件路径 --key=私钥文件路径
3)创建 ingress 资源,引用 tls 类型的 Secret资源
spec:
tls:
- hosts:
- 指定使用 https 访问的目标域名
secretName: 指定tls类型的Secret资源
- 指定使用 https 访问的目标域名
基于 basic-auth 访问认证
1)使用 htpasswd 创建用户数据文件,固定文件名为 auth
2)创建 Secret资源 kubectl create secret generic <资源名称> --from-file=auth
3)创建 ingress 资源,在 annotations 注释字段中添加配置信息
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: Secret资源名称
nginx.ingress.kubernetes.io/auth-realm: ‘窗口提示信息’
基于 rewrite 重写访问路径
创建 ingress 资源,在 annotations 注释字段中添加配置信息
metadata:
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
....
spec:
rules:
- host: "www.kgc.com"
http:
paths:
- pathType: Prefix
path: /something(/|$)(.*)
backend:
service:
name: myapp-ky29
port:
number: 9090
捕获的正则表达式 任何字符(.*) 将其分配给占位符 $2,然后将其用作注释中的参数 rewrite-target
www.kgc.com[:端口]/something 重写为 www.kgc.com[:端口]/
www.kgc.com[:端口]/something/ 重写为 www.kgc.com[:端口]/
www.kgc.com[:端口]/something/new 重写为 www.kgc.com[:端口]/new
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: https://www.accp.com:30443
spec:
rules:
- host: "www.kgc.com"
将任何使用 www.kgc.com 作域名的访问请求,都重写成 https://www.accp.com:30443
metadata:
annotations:
nginx.ingress.kubernetes.io/app-root: /app1
spec:
rules:
- host: "www.kgc.com"
http:
paths:
- pathType: Prefix
path: /
将访问 www.kgc.com[:端口]/ 的请求,都重写成 www.kgc.com[:端口]/app1
pod 的自动伸缩
HPA: Pod水平自动伸缩 为控制器管理的Pod资源副本数量实现自动扩缩容
VPA: Pod垂直自动伸缩 据容器资源使用率自动设置CPU和内存的requests
HPA的实现原理:利用 metrics-server 定期收集 Pod 资源的平均 CPU 负载情况,根据HPA配置的 CPU/内存 requests 百分比阈值来动态调整 Pod 的副本数量
HPA 扩容时,Pod 副本数量上升会比较快;缩容时,Pod 副本数量下降会比较慢
kubectl top nodes|pods
kubectl autoscale <Pod控制器资源> <资源名称> --min=<最小副本数> --max=<最大副本数> --cpu-percent=<CPU requests百分比阈值>
K8S集群管理工具: kubectl命令行管理工具 dashboard(K8S官方的UI界面图形化管理工具) 只能管理单个K8S集群
同时管理多个K8S集群:rancher kubesphere k9s
K8S 的安全机制
> 客户端应用若想发送请求到 apiserver 操作管理K8S资源对象,需要先通过三关安全验证:认证(Authentication)、鉴权(Authorization)、准入控制(Admission Control) > 认证 确认请求方是否有连接 apiserver 的权限 > token认证(通过token字符串来认证) base认证(根据 账户:密码 的格式来认证) https认证(通过6443端口,使用证书和私钥来认证,支持双向认证) > 认证过程 > K8S组件(kubectl、kubelet等)可通过使用cfssl工具手动签发或者通过bootstrap机制自动签发证书,并生成kubeconfig文件,引用其中的集群参数(ca证书、apiserver地址)和客户端参数(证书和私钥)连接到指定的K8S集群的apiserver,默认使用https的6443端口与apiserver通信。 > 以Pod形式运行的组件(dashboard、cni网络插件、外置存储卷插件、ingress控制器等),使用serviceaccount账户作为Pod的服务账户(如果没有指定则默认使用当前命名空间的default),同时K8S也会自动创建相关的service-account-token类型的Secret资源,Pod启动时会自动挂载相关的Secret卷到容器的/var/run/secrets/kubernetes.io/serviceaccount目录,并使用其中的token访问apiserver作认证。 > 鉴权(确认请求方具有哪些资源对象的操作权限) > RBAC(基于角色的访问控制) 包含4个资源对象 Role ClusterRole RoleBinding ClusterRoleBinding > 角色(Role ClusterRole)定义角色能够对哪些 资源对象 拥有哪些 操作权限 > Role 受命名空间的影响,只能在指定的命名空间中操作资源 > ClusterRole 默认能够在K8S集群中所有的命名空间中操作资源,不要配置 namespace > 角色绑定(RoleBinding ClusterRoleBinding)将主体账户subjects(User、Group、ServiceAccount)与角色进行绑定,使得主体账户具有角色相关的资源操作权限 > RoleBinding 可以与相同命名空间的Role绑定,使主体账户在指定的命名空间中具有角色相关的资源操作权限 > 也可以与ClusterRole绑定,使主体账户只在RoleBinding指定的命名空间中具有集群角色相关的资源操作权限 > ClusterRoleBinding 只能与与ClusterRole绑定,使主体账户在所有的命名空间中具有集群角色相关的资源操作权限
如何授权让一个普通用户能够使用 kubectl 在 K8S 中具有操作资源权限?
先 认证 授权
1)签发 kubectl 用户的证书和私钥文件
2)创建 kubectl 的 kubeconfig 集群配置文件,移动并修改文件名为 ~/.kube/config
再 鉴权 授权
3)先创建角色(Role|ClusterRole)
rules:
- apiGroups: [""] #指定 api 组,可参考 kubectl api-resources 的 APIVERSION 字段
resources: ["pods"] #指定授权的 资源名(pods) 或者 子资源名(pods/log)
verbs: ["create", "delete", "get", "list", "watch"] #指定对资源对象的 操作权限
4)给主体账户(User、Group、ServiceAccount)绑定角色(Role|ClusterRole)
kubectl create rolebinding <资源名称> --role=<Role资源名称> --user|group= [--serviceaccount=<命名空间>:<serviceaccount资源名称>] -n 命名空间
kubectl create clusterrolebinding <资源名称> --clusterrole=<Role|ClusterRole资源名称> --user= [--group= --serviceaccount= ]
准入控制(使用额外的准入控制插件对资源请求进行检查,如果检查不通过则会拒绝请求)
K8S在初始化时会默认启用官方推荐的准入控制插件,也可以修改 apiserver 的启动参数 --enable-admission-plugins= 来添加指定的准入控制插件
LimitRanger:用于给指定的命名空间中Pod或容器设置默认的 requests 和 limits 资源量限制
ResourceQuota:用于限制在指定的命名空间中能够创建的最大资源对象数量和 Pod 的 requests|limits 资源量限制
Helm 是K8S的软件包(Chart包)管理器
可以实现将软件应用所有所需的资源配置打包在一起,资源配置还能实现高度的可配置化,并可以通过单个helm命令一键管理部署
Helm 的三大概念:
Chart(软件包) Release(基于Chart运行的实例) Repository(存放Chart的仓库)
Helm 仓库管理命令:
helm repo list #查看chart仓库列表
add <仓库名称> <仓库URL地址> #添加chart仓库
update #更新chart仓库
remove <仓库名称> #删除chart仓库
helm search repo <仓库名称> #查看仓库中可用的chart包列表
helm search repo <仓库名/软件包> -l #查看仓库中此软件包的所有历史版本列表
helm show chart <仓库名/软件包> #查看chart软件包的基本概要信息
helm show all <仓库名/软件包> #查看chart软件包的所有详细信息
Helm 的包安装、卸载命令:
helm install <实例名> <仓库名/软件包> -n <命名空间> [--version=<chart版本>] #根据chart包安装实例
helm ls|list -n <命名空间> #查看指定命名空间下的实例列表
helm status <实例名> -n <命名空间> #查看实例的状态
helm uninstall <实例名> -n <命名空间> #卸载实例
Helm chart软件包管理命令:
helm pull <仓库名/软件包> #从仓库拉取chart压缩包
helm create <chart名称> #创建一个chart目录
helm lint <chart目录> #检查chart配置语法
helm package <chart包目录> #打包成chart压缩包
helm upgrade <实例名> <chart包> -n <命名空间> #升级实例
helm history <实例名> -n <命名空间> #查看实例的历史版本列表
helm rollback <实例名> <版本序号> -n <命名空间> #回滚实例到指定历史版本
helm repo add <私有仓库名> <私钥仓库地址> --username= --password= #添加chart私钥仓库,harbor私钥仓库地址格式为:http://私钥仓库URL地址/chartrepo/项目名
helm push <chart包> <私有仓库名> #推送chart包到私钥仓库
chart包的关键组成:
**Chart.yaml:**描述chart的元信息,包括chart名称(name)、chart版本(version)、应用版本(appVersion)、chart api接口(apiVersion)等
**templates目录:**目录里存放部署应用所需要的各种资源对象的yaml配置模板文件
**values.yaml:**存储 templates目录中yaml配置模板文件中变量的值
"] #指定授权的 资源名(pods) 或者 子资源名(pods/log)
verbs: [“create”, “delete”, “get”, “list”, “watch”] #指定对资源对象的 操作权限
4)给主体账户(User、Group、ServiceAccount)绑定角色(Role|ClusterRole)
kubectl create rolebinding <资源名称> --role=<Role资源名称> --user|group= [–serviceaccount=<命名空间>:<serviceaccount资源名称>] -n 命名空间
kubectl create clusterrolebinding <资源名称> --clusterrole=<Role|ClusterRole资源名称> --user= [–group= --serviceaccount= ]
准入控制(使用额外的准入控制插件对资源请求进行检查,如果检查不通过则会拒绝请求)
K8S在初始化时会默认启用官方推荐的准入控制插件,也可以修改 apiserver 的启动参数 --enable-admission-plugins= 来添加指定的准入控制插件
LimitRanger:用于给指定的命名空间中Pod或容器设置默认的 requests 和 limits 资源量限制
ResourceQuota:用于限制在指定的命名空间中能够创建的最大资源对象数量和 Pod 的 requests|limits 资源量限制
## Helm 是K8S的软件包(Chart包)管理器
可以实现将软件应用所有所需的资源配置打包在一起,资源配置还能实现高度的可配置化,并可以通过单个helm命令一键管理部署
## Helm 的三大概念:
> Chart(软件包) Release(基于Chart运行的实例) Repository(存放Chart的仓库)
## Helm 仓库管理命令:
helm repo list #查看chart仓库列表
add <仓库名称> <仓库URL地址> #添加chart仓库
update #更新chart仓库
remove <仓库名称> #删除chart仓库
helm search repo <仓库名称> #查看仓库中可用的chart包列表
helm search repo <仓库名/软件包> -l #查看仓库中此软件包的所有历史版本列表
helm show chart <仓库名/软件包> #查看chart软件包的基本概要信息
helm show all <仓库名/软件包> #查看chart软件包的所有详细信息
Helm 的包安装、卸载命令:
helm install <实例名> <仓库名/软件包> -n <命名空间> [–version=<chart版本>] #根据chart包安装实例
helm ls|list -n <命名空间> #查看指定命名空间下的实例列表
helm status <实例名> -n <命名空间> #查看实例的状态
helm uninstall <实例名> -n <命名空间> #卸载实例
Helm chart软件包管理命令:
helm pull <仓库名/软件包> #从仓库拉取chart压缩包
helm create <chart名称> #创建一个chart目录
helm lint <chart目录> #检查chart配置语法
helm package <chart包目录> #打包成chart压缩包
helm upgrade <实例名> <chart包> -n <命名空间> #升级实例
helm history <实例名> -n <命名空间> #查看实例的历史版本列表
helm rollback <实例名> <版本序号> -n <命名空间> #回滚实例到指定历史版本
helm repo add <私有仓库名> <私钥仓库地址> --username= --password= #添加chart私钥仓库,harbor私钥仓库地址格式为:http://私钥仓库URL地址/chartrepo/项目名
helm push <chart包> <私有仓库名> #推送chart包到私钥仓库
## chart包的关键组成:
**Chart.yaml:**描述chart的元信息,包括chart名称(name)、chart版本(version)、应用版本(appVersion)、chart api接口(apiVersion)等
**templates目录:**目录里存放部署应用所需要的各种资源对象的yaml配置模板文件
**values.yaml:**存储 templates目录中yaml配置模板文件中变量的值
(yaml配置模板文件变量 {{ .Values.image.repository }} 即对应着 values.yaml 文件中 image.repository 字段的值)
Zz ↩︎