面试题
https://github.com/CypherpunkArmory/UserLAnd/releases
- linux
- mysql
- docker 和 harboe
- k8s
- etcd
- elk
- CICD
- prometheus
- zabbix
- nginx 和 Apache 和 tomcat
- redis
- 单词
- 面试
- 1.Zabbix主动模式与被动模式有什么区别?
- 2.Shell或则python脚本,如何增加对nginx自定义指标监控
- 3.Nginx中配置CPU亲和性
- 4.Linux里面常用的系统命令?
- 5.Mysql主从复制原理及搭建过程?
- 6.半同步复制?
- 7. 主从复制不一致的原因?
- 8.mysql数据库常见的存储引擎及区别?
- 9.用过哪些Mysql压测工具
- 10.用过那些mysql中间件
- 11.对事务的了解及事务的隔离级别,锁类型
- 12.索引结构
- 13.常见的备份工具?你是如何对数据进行备份的
- 14.mysql监控
- 15.mysql优化
- 16.dockerfile中常用的指令有那些?
- 17.docker与虚拟机区别
- 18.宿主机的pid与容器的pid有啥关系
- 19.容器的创建与管理过程:
- 20.Dokcer常用的命令
- 21.Docker网络及使用场景
- 22.Docker容器互联?
- 23.存储驱动类型
- 24.Dokcer中资源隔离及资源限制
- 25.K8s里面是如何实现资源限制的?以及如何实现权限控制的
- 26.K8s中有哪些组件它们各自的功能是,k8s的服务访问流程?
- 26.K8s中的controller,区别replicationController, replicaSet,deployment,HPA
- 27.说说你对k8s探针的了解。
- 28.livenessProbe与readinessProbe区别
- 29.K8s命令中apply与create区别。
- 30.说说k8s中pod的常见状态
- 31.Pod重启策略, 镜像拉取策略
- 32.k8s中kube-proxy三种工作模式,有啥区别
- 33.etcd数据备份与恢复机制。如何备份或恢复数据
- 34.你在k8s中用过那些网络组件
- 35.Apache三者工作模式
- 36.Tomcat性能优化
- 37.Nginx如何优化
- 38.如何统计网站访问量
- 39.有一个日志文件比较大导致空间沾满,如何快速释放磁盘空间
- 40.F S服务器还有空间但是上传不了图片的原因?
- 41.常见的raid类型
- 42.软连接和硬链接区别
- 43.有状态和无状态的服务区别
- 44.四层和七层负载区别-处理用户请求有什么不同
- 45.常用的负载均衡的软件有哪些,有什么区别?
- 46.Nginx,haproxy,lvs的调度算法(负载均衡策略)
- 47.Cookie和session功能是什么?Tomcat session共享怎么做,如何共享
- 48.浏览器输入地址后发生了什么
- 49.DNS解析过程
- 50.日志收集大概流程
- 51.Zabbix如何自定义监控项?如何监控mysql,redis?
- 52.简述osi七层模型,和简述每层的功能
- 53.Linux启动流程,以及启动级别
- 53.进程和线程的区别?
- 54.描述/etc/fstab文件中每个字段的含义
- 55.打印 /etc/passwd 的 1 到 3 行
- 56.iptables与fireward区别
- 57.tcp与udp的区别
- 58.说说常见的状态码,如301等
- 59.请问当用户反馈网站访问慢,你会如何处理?
- 60.代码部署上线流程
- 61.系统io模型
- 62.nginx常用模型
- 1.问:主要是跑什么业务
- 2.问:Master也可以调度服务是吗
- 3.问:Etcd数据的备份是怎么做的
- 4.问:安装的k8s版本是多少
- 4.1 问:安装的docker版本是多少
- 4.2 问:harbor的版本
- 5.问:测试生产都是一样的吗(版本)
- 6.问:master默认是不可调度服务的,怎么设置污点
- 7.问:我现在有三个work节点,其中一个work节点出问题了,怎么把这个节点设置成为不可调度服务,然后维修这个节点
- 8.问:如何查看pod跑在哪个机器上,他的ip是什么,什么是什么可以查出来
- 9.问: 起三个pod,然后这三个pod要调度到三个不同的node节点上,如何设置(三个同样的服务,三个副本数,跑在不同的节点上)
- 11.问:需要指定一下docker本身镜像存储的路径,需要怎么配置
- 15.问:现在有一个集群需要配置一个harbor,如何配置
- 16.问:harbor启动的有问题,先停止在启动,是如何操作的
- 17.问:harbor镜像的同步有做过吗(生产 和测试 场景是网络隔离的,测试一个harbor,生产一个harbor ,这两个镜像如何同步过去)
- 18.问:k8s的升级操作做过吗(替换了哪几个文件,执行了哪几个命令)
- 19.问:证书是有时间限制的,时间到期了如何续租
- 20.问:现在要部署一个nginx服务,然后这个nginx服务的配置文件做持久化存储,然后启动三个副本数,把服务暴露出来,这种是怎么配置的
- 21.问:设置副本数为3个的参数是什么
- 22.问:把服务布置好了,然后需要把这个服务提供出来访问,那么访问方式有几种
- 23.问:service和deployment怎么就可以通信了
- 1.问:什么环境可以描述一下吗,生产环境,测试环境,大概跑的量,和服务器的配置大概描述一下
- 2.问:calico的BGP说一下。calico的几种网络模式,各自都是什么原理,优势是啥说一下
- 3.问: 主要的是跑什么业务
- 4.问:pod终止过程说一下
- 5. log stash这个组件具体是干什么的,实现什么功能说一下
- 6. flannel几种网络模式说一下,说一下flannel的Host Gate Way模式 和 calico的BGP模式啥区别说一下
- 7. 创建pod的流程,各组件都起啥作用说一下
- 8. k8s 1.23版本以后不支持docker了,都用containerd了。说说这两种有啥区别说一下
- 9. 容器 (即pod) 生命周期
- 两个不同的pod的两个不同服务比如nginx和mysql是通过coerDNS定义pod解析的域名通信的
- iptables和ipvs的区别优势是什么
- namespace资源隔离都隔离了哪些
- 如何更改kube-porxy的网络模式,以及算法
- 使用nodeport访问程序是什么流程
- 单纯启动一个pod需要经过controller-manager吗
- awk取第二行的第二列
- 使用sed把大写的A替换成小写的a
- 查看java的所有进程
- Maven 的编译命令
- prometheus监控node
- prometheus监控容器
- prometheus告警组件
- 1. 平时写dockerfile吗,简单说一下dockerfile
- 2. copy和add这两个dockerfile命令的区别
- 3. docker run参数
- 4. 容器起来之后,一直处于自动重启的状态,说一下排查思路
- 5. 查看容器状态的命令,说两个
- 6. 工作中用到的docker版本
- 7. 说一下k8s组件
- 8. 说一下pod创建过程
- 9. 运行pod的时候有很多节点,牵扯到pod一个亲和和反亲和,服务启动如何保证pod启动在指定的节点上
- 10. k8s集群环境有多少节点
- 11. yaml文件中service的一些port , targetPort ,nodepod都是什么意思
- 12. service和pod之间的关系
- 14. 平时中说用的挂载所用的挂载使用那个(就是让说configmap)
- 15. 公司中用helm,chart吗
- 16. 一个服务是如何起到k8s中的
- 17. 起的pod现在发现有几十个都处于被驱逐的状态,这个会是什么情况导致的
- 18. 批量删除指定状态的pode
- 19. 简单说一下pod状态
- 20. redis备份
- 22. 查询一个tast表中,每一个tast列,中包含字符tast所有的条目
- 23. nginx反向代理和正向代理的区别
- 24. nginx中master进程和work进程说一下他俩的区别
- 25. nginx平滑升级
- 26. kafka和ZooKeeper
- 27. shell如何批量修改文件中的通用字符串,说一下有几种方式
- 28. 使用什么linux服务器,内核是多少
- 29. linux免密登录
- 31. su 和 sudo的区别
- 32. 开机自动挂载磁盘
- 33. 如何查询进程的启动时间
- 1.什么是redis
- 2.redis的数据类型
- 3.使用redis有哪些好处
- 4.redis相比Memcached有哪些区别和优势
- 5.redis的持久化机制是什么各自的优缺点
- 6.redis主从复制过程
- 7.redis集群哨兵
- 8.rediscluster
- 单词发音
- 20230711
- nginx
- server1安装keepalived和tcpdump抓包软件
- server1安装keepalived和tcpdump抓包软件
- server1编辑配置文件
- 配置文件直接拷贝到server2中
- server2编辑修改一下配置文件
linux
示例
mysql
docker 和 harboe
示例
Dokcer中资源隔离及资源限制(cgroup如何做资源限制,如何配置)
问:需要指定一下docker本身镜像存储的路径,需要怎么配置
问:harbor镜像的同步有做过吗(生产 和测试 场景是网络隔离的,测试一个harbor,生产一个harbor ,这两个镜像如何同步过去)
k8s
示例
重复-k8s中有哪些组件它们各自的功能是k8s的服务访问流程(也就是使用nodeport访问程序是什么流程)
calico的bgp说一下calico的几种网络模式各自都是什么原理优势是啥说一下
flannel几种网络模式说一下说一下flannel的HostGateWay模式和calico的bgp模式啥区别说一下
(不同pod的两个容器是如何通信的)两个不同的pod的两个不同服务,比如nginx和mysql是通过coerDNS定义pod解析的域名通信的
k8s 1.23版本以后不支持docker了都用containerd了说说这两种有啥区别
起三个pod然后这三个pod要调度到三个不同的node节点上如何设置三个同样的服务三个副本数跑在不同的节点上
没用-k8s中的controller区别replication controller, replicaset,deployment,hpa
重复-平时中说用的挂载所用的挂载使用那个就是让说configmap
起的pod现在发现有几十个都处于被驱逐的状态这个会是什么情况导致的
没看懂-节点已经恢复了现在状态还是需要我们手动批量给delete掉说一下这个命令
问:我现在有三个work节点,其中一个work节点出问题了,怎么把这个节点设置成为不可调度服务,然后维修这个节点
问:如何查看pod跑在哪个机器上,他的ip是什么,什么是什么可以查出来
问:k8s的升级操作做过吗(替换了哪几个文件,执行了哪几个命令)
问:现在要部署一个nginx服务,然后这个nginx服务的配置文件左持久化存储,然后启动三个副本数,把服务暴露出来,这种是怎么配置的(涉及到哪几个文件,哪几个配置参数,正常使用的时候最基本的使用场景)
问:把服务布置好了,然后需要把这个服务提供出来访问,那么访问方式有几种
问:service和Deployment是怎么关联上的,service和Deployment怎么就可以通信了呢
etcd
elk
CICD
prometheus
zabbix
nginx 和 Apache 和 tomcat
示例
Nginx中配置CPU亲和性,worker_processes 和worker_cpu_affinity有什么好处
nginx
Apace模型
prefork模型,一个主进程生成多个子进程,每个子进程生成一个线程处理用户请求
woker模型,一个主进程生成多个子进程,每个子进程生成多个线程处理用户请求
event模型,和woker模型类似,区别多了一个监听线程负责向工作线程分配任务并
和客户端保持会话连接
系统I/O模型
同步: 调用者主动询问内核事情是否处理完成
异步: 内核主动返回状态给调用者
阻塞: 结果返回之前,调用者被挂起,⼲不了别的事情
⾮阻塞: 结果返回之前,调用者被挂起,⼲不了别的事情
Nginx常用模型
select:
poll:
epoll:异步非阻塞
redis
示例
单词
面试
示例
大厂一般四面,三面技术 + 一面薪资
一面:同事面
(面技术,把简历写到的和工作中要用到的都会问到位,时间至少1小时)
二面:直属TL(领导)面
(TL面,不仅仅面技术,主要贴近项目业务)
三面:总监面
(总监面,一般比第一面和第二面容易,可能主要是大的架构方向和思想,价值是否符合)
四面:HR面
(HR压薪资,HR是有kpi的,发了几个offer,有几个高级和低级,低级发了高级的薪资这说不过去,岗位有薪资标准,但是我们还是可以争取)
(薪资多轮争取,一个公司中在面试一个岗位的时候,他会面试至少四五十人,然后进入到候选池里面,至少有三到五个人左右,防止发了offer后放鸽子 ,HR要在这三到五个人中权衡薪资和能力,为什么说同样两个人,能力差不多,工作岗位差不多,但是薪资会差几千块,在面试前,自我介绍,面试中回答问题,面试后以及在谈薪阶段,在这些地方差的)
沟通能力
示例
慎入(区别对待!但是门槛低,外包公司经历在简历中尽量包装掉!!)
自我介绍(可以介绍我做过什么项目,但是项目必须熟悉)
示例
去公司面试的时候可能有两轮面试或者三轮面试,但是无论那一轮面试百分之百都会让你说一段自我介绍,大概要说一分多钟左右到三分钟,不要太长也不要太短(自己自拍进行练习,回放感觉效果,要自信)
这个自我介绍就是,基本上从毕业开始,如果没有学历的话,就不要说专业了,就从工作经验说起,说项目,说擅长的技术,所以说面试的原则就是扬长避短,把长处说出来,把短处相对的弱化一下,这个自我介绍一定要多准备点,用文字写出来,不要用脑子空想,今天想的这样,睡一觉之后明天就想的那样了,所以说一定要写出来
比如说对k8s不熟,但是会虚拟化,那么就划重点在项目上多写擅长的技术,比如监控,这个监控还是比较简单的
比如在上一家负责监控的,从监控的规划上说起,我们用了分布式的监控,然后是什么主动模式的,包括我们的监控项是怎么定的,触发器的值是怎么定的,告警的方式是通过邮件还是短信还是微信还是钉钉,然后你的模板是怎么做的,以及这个整合的方案都是怎么实施的,一定要多擅长的
工作经验我们可以把项目着重说一下,而且工作经验一定要和简历对的上,因为我们在说自我介绍的时候,面试官他一般会看我们的简历,你说你的工作经验是什么什么样子,那么面试官会看着简历对一下,不要说的不一样,或者顺序不一样,假如说18年到19年在A公司,结果在自我介绍的时候说18年到19年在另外一个公司,这就麻烦了,所以说工作经验和简历,包括工作年限一定要一模一样,写的什么就是什么
百度外包
- 先对之前的工作方面做一个简单的自我介绍
项目经验
示例
面试过程中面试官大多是顺着自己介绍的项目一直深挖的,比如,我们自己介绍的项目是,日志文件通过flme,kafka然后通过spring boot项目保存到hbase里面去,后续通过spark和mr进行处理
然后面试官问问题:kafka是如何保证excetly once,hbase rowkey是如何设计的。后续使用spark和MapReduce进行处理是map数量和rdd数量是如何控制的
问答问题
示例
注意:当面试官问完问题之后,在我们的角度上复述一遍,确认一遍,在面试官纠正完之后,或者认可之后,我们在作答,避免回答问题南辕北辙
面试官对问的问题其实是有自己的心理预期答案,回答的时候要尽量往这方面靠
回答问题尽量回答全面(使用场景,解决方案,回答问题闭环性),不是很熟悉的点到为止(言多必失!!)
面试官问的问题未必都可以回答上来,面试官对面试者是有一个限度的,比如问了一个问题回答不上来,其实无所谓,问两个回答不上来,还是可以接受,但是问到三个都回答不上来,其实上基本就被pass掉了,尽量将话题往自己熟悉会的领域引导!!!被问到的问题不会,使用自己熟悉的领域,退而求其次帮助其解决,领导仅关系结果,不关心过程
也可以试探性的提问面试官(涨经验,不可能第一次面试就拿到offer了,对自己简历中不完善的情况,直接试探性提问面试官,将结果可以优化到下一次面试中)
你有没有想问我的问题?
示例
一般在面试后,面试官可能会提问
参考回答1:我们当前这部门未来的发展规划大概是什么样子的?
(部门一般都会有目标,比如要上k8s,比如要迁云)
参考回答2:针对我今天的面试有什么有待改进的地方,或者说有什么建议可以给到我!!! (这是试探,比如我们感觉自己面的不行,或者感觉自己面的可以,但是我们最好了解给面试官留下来的印象,如果面试官说你有哪些方面还有待改进,或者你有那些技术掌握还不是很到位,他这样是不是就是在婉拒你了,那么我们就知道了可以不用在考虑他了,就可以去找下一家了,而且这样也是在涨经验,补齐短板,如果面试官可能说差不多,或者你这个人都还不错,那么我们第一面可能没有什么问题了)
1.Zabbix主动模式与被动模式有什么区别?
示例
- 主动模式与被动模式的区别(以zabbix agent为参照)
-
被动模式:也是默认的模式,此模式下zabbix agent需要监听在10050端口,zabbix server端需要像zbabix agent发起数据请求(一般该请求是key,如agent.ping),并且携带需要监控的key(从数据库种取出),然后由zabbix agent采集之后,等待zabbix server取数据。该模式只适用于监控主机不多的环境。
-
主动模式:zabbix agent配置中,会配置zabbix active(zabbix server的地址),以及hostname(定义zabbix agenet服务器地址或域名)。先是zabbix agent打开一个随机端口向zabbix server的10051端口发起连接,获取监控项,然后进行数据采集,采集之后主动发给zabbix server,最后又zabbix server将数据写入数据库(mysql)
-
2.Shell或则python脚本,如何增加对nginx自定义指标监控
示例
-
通过shell脚本获取自定义监控的值,并对脚本赋予执行权限
-
在zabbix agent配置文件中,引用脚本。并重启zabbix agent
-
在zabbix server通过zabbix-get 命令测试监控的值是否能获取成功
- zabbix-get -s IP p PORT -K ”脚本名称[参数]”
-
创建模板,触发器,图形等,并关联到指定的主机上,稍等几分钟后验证数据
3.Nginx中配置CPU亲和性
示例
nginx中配置CPU亲和性,worker_processes和worker_cpu_affinity有什么好处
设置worker_processes 表示启动⼯作进程数数量
work_cpu_affinity 将工作进程和指定cpu做绑定,可以避免nginx的工作进程在不同的cpu做来回切换,避免内存频繁的申请和回收而带来不必要的资源消耗
-
worker_processes和worker_cpu_affinity有什么好处
-
设置work_processes(pro 色色死)数量,可以增加nginx并发访问量
-
work_cpu_affinity(阿飞耐迪)将工作进程和指定cpu做绑定,可以避免nginx的工作进程在不同的cpu做来回切换,避免内存频繁的申请和回收而带来不必要的资源消耗。
-
4.Linux里面常用的系统命令?
示例
Linux里面常用的系统命令
日志:tail -f
文件:grep 和 sed 和 awk
还有 cat,v i m,tail,head,s c p, c p, m v, r m
内存:free -h
Cpu:top
磁盘:df -T H 和 f disk -l
进程:ps -e f
查看日志使用tail命令 -f选项
操作文件,使用grep命令 、sed命令、 awk命令、 cat命令、 c p命令 、m v命令 、r m命令、 less命令 、tail命令
查看内存使用free -h
查看cpu使用top命令
查看磁盘使用df命令 -t h
查看进程使用ps命令 -e f
5.Mysql主从复制原理及搭建过程?
示例
搭建过程,
master节点开启二进制日志,设置唯一id,slave节点开启中继日志,设置唯一id,master节点使用mysql dump命令完全备份数据,并在slave节点导入数据,master节点创建用于主从复制的用户并授权,在slave节点执行change命令 master to指定master节点,并执行start slave,观察io线程和sql线程是否为yes
主从复制原理:
Master节点会开启一个dump线程,用于接受从节点的sync数据请求,slave节点会开启io线程和sql线程。Io线程负责将master发过来的二进制日志写入中继日志中,而sql线程负责从中继日志中读取二进制日志,并执行。
-
搭建过程 :
-
安装神略…
-
开启二进制日志(bin_log),并设置唯一的server_id
-
在master节点使用mysqldump命令完全备份数据,并在slaveJ节点导入数据
-
在master节点创建用于主从复制的用户并授权
-
在slave节点执行change master to,并执行start slave,观察io线程和sql线程是否为yes
-
-
主从复制原理:
- Master节点会开启一个dump线程,用于接受从节点的sync数据请求,slave节点会开启io线程和sql线程。Io线程负责将master发过来的二进制日志写入中继日志中,而sql线程负责从中继日志中读取二进制日志,并执行。
6.半同步复制?
示例
默认情况下,MySQL的复制功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发送给从库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失
7. 主从复制不一致的原因?
示例
原因一,
主库执行更改前误设置set sql_log_bin=0,会使主库不记录binlog,从库也无法变更这部分数据
原因二,
主库binlog格式为statement(一般为row),同步到从库执行后可能导致主从不一致
原因三,
主库或从库意外宕机,可能造成binlog(二进制日志)或relaylog(中继日志)出现损坏,导致主从不一致
原因四,
从节点未设置只读,误操作写入数据
原因五,
主从实例版本不一致,将使某些功能有些许变化
8.mysql数据库常见的存储引擎及区别?
示例
my sql数据库常见的存储引擎及区别
My isam
不支持事务,不支持外键,不支持热备
in no db
支持事务,支持外键,支持热备,温备,冷备
- Memory,CVS,myisam,innodb等
Myisam | Innodb | |
---|---|---|
事务 | 不支持 | 支持 |
聚集索引 | 支持非聚集索引,全文索引 | 支持聚集索引,5.5版本之后支持全文索引 |
外键 | 不支持 | 支持 |
数据备份(热备,温备,冷备) | 不支持热备 | 都支持 |
锁级别 | 表级锁 | 表或行级锁 |
MVCC(多版本访问控制) | 不支持 | 支持 |
优点 | 读取数据快,占用资源少 | 崩溃恢复性更好 |
9.用过哪些Mysql压测工具
示例
用过那些My sql压测工具
mysql slap 命令
-a --concurrency=50,100 --number-of-queries 1000 -uroot
10.用过那些mysql中间件
示例
- mycat:实现读写分离
用过那些my sql中间件
m h a:实现高可用(自动提升slave为master)
gelera cluster:实现mysql高可用以及高并发(多主,集群模式增加my sql写性能)
my cat:实现读写分离
11.对事务的了解及事务的隔离级别,锁类型
示例
ACID特性:
原子性,一致性,隔离性,持久性
隔离级别:
读未提交(可能出现脏数据)
读提交(不可重复读)
可重复读(可能出现幻读)
序列化:未提交的读事务阻塞修改事务(加读锁,但不阻塞读事务),或者未提交的修改事务阻塞其它事务的读写(加写锁,其它事务的读,写都不可以执行)。会导致并发性能差
锁类型:
读锁:共享锁,S锁,只读不可写,多个读互不阻塞
写锁:独享锁,排它锁,X锁,写锁会阻塞其他事务的读和写
12.索引结构
示例
二叉树(容易瘸腿,不平衡),红黑树,B减(高瘦型),B加(矮胖型)等
13.常见的备份工具?你是如何对数据进行备份的
示例
My sql dump 物理备份和 xtra back up 热备份
mysqldump -uroot -p -A -F -E -R --triggers --single-transaction --master-data=2 --flush-privileges --default-character-set=utf8 --hex-blob >${BACKUP}/fullbak_${BACKUP_TIME}.sql
14.mysql监控
示例
show master status;
监控二进制日志位置
show slave status;
监控io和sql线程
show processlist;
监控连接到数据库的线程
show binary logs;
监控二进制日志
15.mysql优化
示例
max_connections=2000 会话连接数
open_files_limit= 10240 所有线程打开表的数量
back_log=300 操作系统在监听队列中能保持的连接数
max_allowed_packet=32M 每个连接传输数据大小,最大1G
wait_timeout=10 指定请求的最大连接时间
query_cache_size= 128M 指定查询能够使用的缓冲区大小
transaction_isolation=REPEATABLE-READ 事务的隔离级别
log-bin=/data/mysql/log-bin 二进制日志
binlog_format=row 二进制日志格式
innodb_file_io_threads = 4 用来同步io线程的数量
innodb_log_file_size=512M 在日志组中每个日志文件的大小
long_query_time=2 慢查询时间
16.dockerfile中常用的指令有那些?
示例
dockerfile中常用的指令有那些
FROM 指定基础镜像
Maintainer 注释信息,作者,日期等
RUN 执行非交互式的shell命令
COPY 将宿主机的文件复制到容器中
ADD 将宿主机的文件复制到容器中,并且会自动解压tar点g z格式的压缩包
ENV 定义容器环境,一般my sql会用到
USER 运行服务的用户
Volume 将宿主机的某目录挂载到容器中,一般是某些配置文件,且宿主机的目录也是挂载到共享存储上
EXPOSE 声明容器中要暴漏的端口(或者说映射到宿主机上的端口)
CMD 启动服务,运行一个占据终端且pid为1的进程。一般是运行一个脚本或某服务的启动[需要关闭后台运行
17.docker与虚拟机区别
示例
虚拟机模拟硬件,安装完整的内核
容器通过隔离出一个独立空间,共享宿主机内核
18.宿主机的pid与容器的pid有啥关系
示例
容器的pid就是宿主机的子pid,只不过隔离起来了,在容器看起来他的pid就是1
19.容器的创建与管理过程:
示例
docker run 命令 创建容器 使用--name 指定容器名称 -p 指定映射的端口号 最后指定镜像
20.Dokcer常用的命令
示例
镜像的导入导出: docker load/save
镜像的上传和下载: docker push/pull
镜像的构建:docker build
镜像的构建过程:docker history
删除镜像 docker r m i
容器的运行:docker run
以测试的方法运行容器:docker run --rm
进入正在运行的容器:docker e x e c
查看容器的详细信息:docker inspect
查看容器:docker p s
删除容器:docker r m
宿主机与容器之间进行文件拷贝:docker c p
21.Docker网络及使用场景
示例
none:没有网络信息,只有一个回环地址
host:网络模式中性能最强的,与宿主机共享一个网路空间
container:寄生模式,共享一个网络空间,两个容器之间可以通过 l o网卡和容器ip地址通信。
Bridge:桥接模式,为每个容器分配一个网络空间,各容器通过docker0(虚拟网桥)与宿主机连接
22.Docker容器互联?
示例
单机场景下通信:
同一网段:通过容器名称
不同网络:利用ip table s规则
跨主机通信:
各宿主机不在同一个网段: 在宿主机上添加路由
23.存储驱动类型
示例
docker默认使用的存储引擎为overlay2
从3.18开始就进入了Linux内核;资源消耗更少
24.Dokcer中资源隔离及资源限制
示例
Dokcer中资源隔离及资源限制
namespace(资源隔离);
c groups(资源限制)
运行容器时通过-m --cpu指定内存和cpu限制
c group 的主要作用:管理资源的分配、限制;在etc目录下的c gconfig.conf配置
25.K8s里面是如何实现资源限制的?以及如何实现权限控制的
示例
- Resourcequota(瑞烧死寇二达) 实现对命令空间的资源进行限制。
示例
apiVersion: v1
kind: ResourceQuota # 资源类型ResourceQuota针对于整个namespace的资源总数进行限制
metadata:
name: quota-helloworld # 此名称是资源限制的名称,这个名称无所谓
namespace: helloworld # 创建在哪个namespace,他就在哪个namespace生效,限制helloworld这个namespace
spec:(四百克)
hard:(孩的)
requests.cpu: "2" # 单个pod的cpu最大是2个,限制pod最好限制最大使用cpu,要不然就别写
requests.memory: 4Gi # 单个pod的内存最大时4G,限制pod最好限制最大使用内存,要不然就别写
limits.cpu: "8" # Limits是硬限制,硬限制可以高点,硬限制cpu是8个
limits.memory: 16Gi # Limits是硬限制,硬限制可以高点,硬限制内存内存是16G
requests.nvidia.com/gpu: 4 # requests.英伟达.com/gpu,最多允许单个pod使用英伟达的GPU核心,如果有的话可以写
pods: "2" # 限制pod,最多能创建几个pod,这个限制此namespace中最多创建2个pod,不对创建限制之前的pod进行限制
services: "6" # 限制service,最多能创建几个service,这个限制此namespace中最多创建6个service
- Limitrange 实现对单个容器使用的资源进行限制。
示例
apiVersion: v1
kind: LimitRange # 指定资源类型是LimitRange
metadata:
name: limitrange-helloworld # 名称是什么
namespace: helloworld # 在哪个namespace中创建
spec:(四百克)
limits: # 在limits当中指定限制类型
- type: Container(肯恩腿哪儿) # 限制的资源类型是Container,这个Container是限制单个pod中的容器
max: # 最大(这些值可以自己去定义,在创建容器的时候就不能超过这个值了,如果超过这个值他就又拒绝创建了)
cpu: "1" # 限制单个容器的最大CPU
memory: "500Mi" # 限制单个容器的最大内存
min: # 最小(这些值可以自己去定义)
cpu: "200m" # 限制单个容器的最小CPU
memory: "128Mi" # 限制单个容器的最小内存
default:(得否特) # 默认值(如果容器在创建的时候没有加限制的话,就给他提供这个值)
cpu: "490m" # 默认单个容器的CPU限制
memory: "256Mi" # 默认单个容器的内存限制
defaultRequest:(得否特 锐阔挖斯特) # 容器在被调度的时候,宿主机最少要有这么多资源
cpu: "256m" # 默认单个容器的CPU创建请求
memory: "256Mi" # 默认单个容器的内存创建请求
maxLimitRequestRatio: # 如果说调度的时候defaultRequest中的memory写的是256Mi,那么就限制他的硬限制是此值的2倍,但是这个值一般不写,硬限制都是通过max去定义的
cpu: 2 # 限制CPU Limit/request比值最大为2(request如果是2个的话,Limit就是4个,比值可以乘以2)
memory: 1.5 # 限制内存limit/request比值最大为1.5(如果request内存是1.5的话,那么最多pod可用内存是3G,这个比例就是1比几的意思)
- type: Pod # 类型是pod,针对pod进行限制要相对高点
max: # 最大
cpu: "1" # 限制单个Pod的最大CPU是1核
memory: "1Gi" # 限制单个Pod最大内存1G
- type: PersistentVolumeClaim # 类型是pvc(这个其实是网络存储)
max: # 最大
storage(是到耳机): 50Gi # 限制PVC最大的requests. storage
min: # 最小
storage: 30Gi # 限制PVC最小的requests, storage
- 权限:使用rbac,基于角色的访问控制(RBAC)是一种基于企业内个人用户的角色来管理对 计算机或网络资源的访问的方法。
- Role(揉哦)是单独的一个权限,设置为一个账号
- ClusterRole是集群的一种角色,对集群进行管理的
- RoleBinding 和 ClusterRoleBinding 进行绑定的,角色在授予权限之后,他是需要对某些账号进行绑定,如果是一个普通角色需要使用RoleBinding绑定给哪些哪些账号,如果想授予他对k8s集群的管理权限要使用ClusterRoleBinding把他绑定给哪些哪些账号
示例
kind: Role # 这个资源对象叫Role,通过kubectl api-resources查看查看,他的NAMESPACED为true,这个资源对象是需要namespace的,KIND显示简称Role
apiVersion: rbac.authorization.k8s.io/v1 # api版本,这个api版本要和当前的k8s集群中的资源对象版本一致,可以使用kubectl api-resources查看
metadata:
namespace: helloworld # 在命名空间helloworld中创建,也可以理解为对helloworld命名空间进行授权,如果helloworld这个命名空间中有pod我们可以登录Dashboard后看到
name: helloworld-role # Role名称
rules:(如肉丝)
- apiGroups: ["*"] # apiGroups可以写好几个
resources(瑞少儿瑟斯): ["pods","pods/exec"] # resources指定资源对象,这里对pods和pods下的exec(exec这是在pod中执行命令的,如果不写这个的话,他在pod里是执行不了命令,也进不去,根本无法执行shell环境)这两个资源对象,apiGroups指定的那个“*”表示所有api版本全部授权给helloworld-role这个Role
#verbs: ["*"]
#RO-Role
verbs(闻儿不撕): ["get", "watch", "list","create"] # 这个verbs就是动作,授权给这个role什么权限,比如上传,删除,创建等等这些动作,如果下“*”表示授权他登录进去之后所有动作都允许,或者指定一部分,这里指定仅能让他"get", "watch", "list","create"这些基本操作,但是一般我们会禁止他删除
- apiGroups: ["extensions", "apps/v1"]
resources: ["deployments"] # 针对deployments控制器资源对象的,让这个控制器有什么什么操作,他可以对容器进行删除,或者是更新等等这些操作,但是这一步这个操作我们不需要开发操作,我们运维去执行代码升级等操作,如果想限制他的操作,后期可以把他创建,删除等这种危险级别比较高的操作给他去掉,这里添加这个控制器用作验证
#verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
#RO-Role # 只读,
verbs: ["get", "watch", "list"]
kind: RoleBinding # 指定资源类型,RoleBinding是角色对账号的绑定
apiVersion: rbac.authorization.k8s.io/v1 # RoleBinding资源对象的api版本
metadata:
name: role-bind-helloworld # 这个RoleBinding的名称
namespace: helloworld # 在helloworld这个namespace中创建
subjects(纱布 杰克特):
- kind: ServiceAccount # 指定账号是什么
name: laomao # 账号是laomao
namespace: helloworld # 账号在helloworld这个namespace
roleRef(揉哦): # 指定把helloworld这个namespace下的laomao这个账号,绑定到哪个role规则
kind: Role # 指定规则是Role
name: helloworld-role # 指定规则名称,RoleBinding通过名称调用这条规则
apiGroup: rbac.authorization.k8s.io # role的api版本
26.K8s中有哪些组件它们各自的功能是,k8s的服务访问流程?
示例
-
组件:
-
Kube-apiserver:为集群的共享前端访问入口,为资源对象提供验证并配置数据,kubernetes中的所有组件都与之交互,唯一能与etcd交互
-
Kube-scheduler:kubernetes调度器,负责将pods指派到合法的节点上(及把最终的指派结果通过apiserver存放到etcd中)。 设置策略,亲和与反亲和等规范
- kube-scheduler通过调度算法为待调度Pod列表的每个Pod从可用Node列表中选择一个最适合的Node,并通过api server将信息写入etcd中,node节点上的kubelet通过API Server监听到kube-Scheduler产生的Pod绑定信息,然后获取对应的Pod清单,下载Image,并启动容器。
- kube-scheduler优选策略
- LeastRequestedPriority: 优先从备选节点列表中选择资源消耗最小的节点(CPU+内存)。(默认策略)
- CalculateNodeLabelPriority: 优先选择含有指定Label的节点。(A项目的容器,仅跑在A项目的服务器上,通过nodeSelector来实现的)
- BalancedResourceAllocation: 优先从备选节点列表中选择各项资源使用率最均衡的节点。(挑选资源使用比较均衡的优先调度,而不是比如内存使用比较低,但是cpu使用率比较高的节点去运行pod)
- kube-scheduler优选策略
- kube-scheduler通过调度算法为待调度Pod列表的每个Pod从可用Node列表中选择一个最适合的Node,并通过api server将信息写入etcd中,node节点上的kubelet通过API Server监听到kube-Scheduler产生的Pod绑定信息,然后获取对应的Pod清单,下载Image,并启动容器。
-
Kube-controller-manager:集群内部的管理中心,负责集群中的node,pod副本,服务断点,命令空间,服务账户,资源定额的管理。当某个Node意外宕机时,Controller Manager会及时发现并执⾏⾃动化修复流程,确保集群中的pod副本始终处于预期⼯作状态。
-
Kube-haproxy:网络代理,调用宿主机内核维护pods网络规则并执行连接转发来实现kubernetes服务访问。以及监听与kube-apiserver发现定义的服务,并能够通过一组后端进行简单的tcp,udp流转发。简单来说:调用宿主机内核,创建iptables或ipvs规则,通过这些规则,我们可以实现对特定的service进行访问
-
Kubelet:运行在node节点上的执行者,它会监视宿主机上的pod资源,并向master汇报node节点的状态信息(健康检查[探针技术实现])。以及通过paiserver执行kube-scheduler调度分配至etcd中存取的任务
-
etcd:默认的k/v数据存储系统,保存所有集群数据,支持分布式集群功能。
-
-
访问流程:
- k8s前面一般有个负载均衡器,当我们访问负载均衡器时,它会转发至那些node节点上那些nodeport,这些nodeport再转发至service,service根据label标签选择器(selector),把请求转发至后端pod,如果后端pod有相互调用,那么pod会根据service(会自动筛选和匹配,把那些符号条件的pod自动添加到当前service的endpoint中)去调用其他pod。
26.K8s中的controller,区别replicationController, replicaSet,deployment,HPA
Replication Controller
-
Replication Controller:副本控制器(selector = !=)
-
他在筛选我们的pod的时候,对资源的标签匹配使用这种" = "严格相等或者" != "不相等(取反)这种操作符,就没有其它的这种模糊匹配,正则匹配等等,他早期可能没有考虑那么多,这个副本控制器能维持指定副本就行
ReplicaSet
-
ReplicaSet:副本控制集,和副本控制器的区别是:对选择器的支持(selector(色莱克特) 还支持in(引) notin(no疼n))
-
ReplicaSet也是一种副本控制器和Replication Controller的区别是在对于容器的选择除了" = " 和 " != "还支持in和notin,in和notin就是支持这种模糊匹配,这个控制也曾短暂使用过,后来就被Deployment取代了
Deployment
- 比rs更高一级的控制器,除了有rs的功能之外,还有很多高级功能,,比如说最重要的:滚动升级(kubectl set image)、回滚(kubectl rollout )等
HPA
-
HPA(Horizontal Pod Autoscaler)的控制器,用于实现基于pod中资源(CPU/Memory)利用率进行对pod的自动扩缩容功能的实现
-
Metrices(买却谁死) Server(单独组件需要安装)完成数据采集
# 安装后验证metrics-server 是否采集到node数据(metrics-server起来之后,有一段时间的数据采集周期)
root@k8s-master1:/opt/metrics-server# kubectl top nodes --use-protocol-buffers
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
10.0.0.13 173m 17% 446Mi 176%
10.0.0.14 214m 21% 484Mi 191%
10.0.0.15 193m 19% 515Mi 203%
10.0.0.3 654m 32% 1033Mi 101%
10.0.0.4 755m 37% 1083Mi 106%
10.0.0.5 774m 38% 1070Mi 105%
root@k8s-master1:/opt/metrics-server# kubectl top pod -n helloworld --use-protocol-buffers
NAME CPU(cores) MEMORY(bytes)
helloworld-nginx-deployment-76bcb4dd64-x9bkl 1m 2Mi
helloworld-tomcat-app1-deployment-5f79d5dd8c-k7lft 2m 85Mi
helloworld-tomcat-app1-deployment-5f79d5dd8c-rkfll 3m 80Mi
helloworld-tomcat-app2-deployment-54f8d46bf4-flbv4 2m 80Mi
# CPU(cores) 表示cpu使用率,m表示毫核,1000毫核是就是1核
# MEMORY(bytes) 表示已用内存
- 修改controller-manager启动参数
# 编辑kube-controller-manager.service文件
root@k8s-master1:/opt/metrics-server# vim /etc/systemd/system/kube-controller-manager.service
...
--horizontal-pod-autoscaler-sync-period=10s \ # 添加此参数
...
- 重启controller-manager,并验证参数是否生效
# 重启controller-manager
root@k8s-master1:/opt/metrics-server# systemctl daemon-reload
root@k8s-master1:/opt/metrics-server# systemctl restart kube-controller-manager
# 查看进程是否生效(可以看到horizontal-pod-autoscaler-sync-period此参数已经生效了)
root@k8s-master1:/opt/metrics-server# ps -ef | grep kube-controller-manager | grep horizontal-pod-autoscaler-sync-period
27.说说你对k8s探针的了解。
示例
- Probe是由kubelet对容器执行的定期诊断。要执行诊断,kubelet调用容器实现的handler(处理程序)。有三种类型的处理程序:
- ExecAction(exec 阿克神):在容器内执行指定命令。如果命令退出时的返回码为0,则认为诊断成功。
- TCPSocketAction(tcp socket 阿克神):对容器的ip地址上的指定端口执行tcp检查。如果端口打开,则诊断被认为时成功的
- HTTPGetAction(http get 阿克神): 对容器的ip地址上指定端口和路径执行HTTP Get请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的。
28.livenessProbe与readinessProbe区别
示例
-
LivenessProbe(来奈斯 pro 部):
- 告诉kubelet对pod执行探测之后是否对pod进行重启
- 无论pod探测结果如何,都会把pod地址加入到service的endpoint中
-
ReadinessProbe(Read 乃是 pro 部):
- 即使探针探测失败也不会重启pod
- 探测失败后不会把pod地址加入到service的endpoint中
29.K8s命令中apply与create区别。
示例
K8s命令中apply与create区别。
apply更新,在第一次通过文件创建资源后,可再次执行更新,增量更新
create创建,必须首次创建,不可重复创建,一次性的全量创建
30.说说k8s中pod的常见状态
示例
-
Pending(悬决):正在创建pod但是pod中的容器还没有全部被创建完成,处于此状态的pod应该检查pod依赖的存储是否有权限挂载,镜像是否可以下载,调度是否正常。
-
Failed(菲欧:失败的):pod中有容器启动失败而导致pod工作异常。如配置文件错误。
-
Unknown(哦闹哦:未知):由于某种原因无法获得pod的当前状态,通常是由于与pod所在node节点通信错误或超时。(如当前pod所在的node上的kubelet没有及时汇报当前node的状态)
-
Successded(谁渴死赛死得:成功):pod中的所有容器都被成功终止,即pod里所有的容器均已被terminated(终止)
-
Unschedulable(昂死该久了不:不定期):pod不能被调度,kube-scheduler没有匹配到合适的node节点。一般是由于创建该pod所需要的资源太多。资源不足而导致。
-
Podscheduled(pod 死该久的:已预定):pod处于调度中,在kube-shcheduler该开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd中的数据,将pod分配到指定的node。出现这种原因很可能是创建的pod需求过多而导致(kubescheduler需要一个一个创建)
-
Initialized(:初始化):所有pod中的初始化容器已经完成了。如MySQL主从,需要同步数据;容器的环境初始化
-
Imagepullbackoff(: 图像回退):pod所在的node节点下载镜像失败。有可能是该节点上没有指定私有仓库的位置(/lib/system/system/docker.service文件--insecure-registry参数)或没有登录
-
Running:pod内部的容器已被创建并且启动。
-
Ready(乳癌第:准备好):表示pod中的容器已经可以提供访问服务
-
terminating(特摸内定:终止)
31.Pod重启策略, 镜像拉取策略
示例
-
Pod重启策略
-
restartPolicy:(restart 爬乐谁一)
- always(欧威):当容器异常时,k8s自动重启该容器,replicationcontroller/reolicaset/deployment
- OnFailure(昂 分类而): 当容器失败时(容器停止且退出状态码不为0),k8s自动重启该容器
- Never(奶味儿):不论容器运行状态如何都不会重启该容器
-
镜像拉取策略
-
imagePullPolicy:(image pull 爬乐谁一)
- Always(欧威) : 默认值,每次重建pod都会重新拉取镜像
- Never(奶味儿) 从不到镜像中心拉取镜像,只使用本地镜像
- IfNotPresent(if not 怕甚特) node节点没有此镜像就去指定的镜像仓库中拉取,node有就是要node本地镜像。
32.k8s中kube-proxy三种工作模式,有啥区别
示例
k8s中kube-proxy三种工作模式,有啥区别
User Space ,k8s,1.2版本以后淘汰
IPtables, k8s,1.2开始默认支持,为防火墙而设计的,逐行匹配规则,时间成本高
IPVS, k8s,1.11默认支持,专门用于高性能负载均衡,通过哈希表匹配规则,有丰富的调度算法
UserSpace k8s v1.2及以后就已经淘汰
IPtables 目前默认方式,1.1开始支持,1.2开始为默认,
IPVS 1.9引入到1.11正式版本,需要安装ipvsadm、ipset工具包和加载ip_vs内核模块
Userpace: 影响处理效率(报文需要在用户空间和内核空间来回拷贝)
iptables: 逐行匹配规则,故在iptables中,范围约下的,往前方。
使用IPVS模式,Kube-Proxy会监视KubernetesService对象和Endpoints,调用宿主机内核Netlink接口以相应地创建IPVS规则并定期与KubernetesService对象Endpoints对象同步IPVS规则,以确保IPVS状态与期望一致,访问服务时,流量将被重定向到其中一个后端Pod,IPVS使用哈希表作为底层数据结构并在内核空间中工作,这意味着IPVS可以更快地重定向流量,并且在同步代理规则时具有更好的性能,此外,IPVS为负载均衡算法提供了更多选项,例如:rr(轮询调度)、lc(最小连接数)、dh(目标哈希)、sh(源哈希)、sed(最短期望延迟)、nq(不排队调度)等。
33.etcd数据备份与恢复机制。如何备份或恢复数据
示例
- WAL是write ahead log的缩写,顾名思义,也就是在执行真正的写操作之前先写一个日志,预写日志。wal: 存放预写式日志,最大的作用是记录了整个数据变化的全部历程。在etcd中,所有数据的修改在提交前,都要先写入到WAL中。
- 方法一:
DATE=`date+%Y-%m-%d_%H-%M-%S` ETCDCTL_API=3 /usr/bin/etcdctl snapshot(死耐普夏尔特) save /data/etcd-backup-dir/etcd-snapshot-${DATE}.db
ETCDCTL_API=3 etcdctl snapshot(死耐普夏尔特) restore(瑞思兜儿) snapshot.db --data-dir=/opt/etcd-testdir
- 方法二
./ezctl backup k8s-01
./ezctl restore k8s-01
34.你在k8s中用过那些网络组件
示例
-
Calico是一个纯三层的网络解决方案,为容器提供多node间的访问通信,calico将每一个node节点都当做为一个路由器(router),各节点通过BGP(Border Gateway Protocol) 边界网关协议学习并在node节点生成路由规则(在服务器上安装好之后,可以在服务器装个组件,当做路由器使用,其实就是通过发送某些报文,能够自动学习在k8s环境内的那些路由表,自动维护路由表),从而将不同node节点上的pod连接起来进行通信。
-
flannel由CoreOS开源的针对k8s的网络服务,其目的为解决k8s集群中各主机上的pod相互通信的问题,其借助于etcd维护网络IP地址分配,并为每一个node服务器分配一个不同的IP地址段(以保证每个节点上起的容器的网段不一样)
-
IPIP可以实现跨不同网段建立路由通信,但是会存在安全性问题,其在内核内置,可以通过Calico的配置文件设置是否启用IPIP,在公司内部如果k8s的node节点没有跨越网段建议关闭IPIP
- IPIP是一种将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式。启用IPIP模式时,Calico将在各Node上创建一个名为"tunl0"的虚拟网络接口。
- BGP模式则直接使用物理机作为虚拟路由路(vRouter),不再创建额外的tunnel。
35.Apache三者工作模式
示例
Apache三种工作模型
Prefork模型:一个主进程生成多个子进程,每个子进程生成一个线程处理用户请求
Worker模型:个主进程生成多个子进程,每个子进程生成多个线程处理用户请求
Events模型:和woker模型类似,区别多了一个监听线程负责向工作线程分配任务并和客户端保持会话连接
-
Prefork:一个主进程生成多个子进程,每个子进程有一个独立的线程处理用户请求。最大支持并发C10K,且占用资源。适用于访问量不是很大的场景。
-
Worker:多进程和多线程的混合模型。一个控制进程启动多个子进程,每个子进程里包含固定的线程来处理请求。高并发场进行无线程可用(在开启keepalive的长连接,某个线程会长时间备占据,及时没有数据传输也会等到超时后才会释放)
-
Events:多进程和多线程的混合模型。与worker模型相比,event模型会在每个子进程的线程中加入一个专门负责监听的线程。
36.Tomcat性能优化
示例
JVM 和 Tomcat 自身调优
内存空间优化
线程池调整
禁用dns查询
设置sessino过期时间
JVM 和 Tomcat 自身调优两部分。
内存空间优化(catalina.sh )
JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize = -xx:maxnewsize "
-server:服务器模式
-Xms:堆内存初始化大小
-Xmx:堆内存空间上限
-XX:NewSize=:新生代空间初始化大小
-XX:MaxNewSize=:新生代空间最大值
线程池调整(server.xml)
connectionTimeout :连接超时时长,单位ms
maxThreads="600" ///最大线程数
minSpareThreads="100"///初始化时创建的线程数
maxSpareThreads="500"///一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。
acceptCount="700"//指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理
URIEncoding:URI 地址编码格式,建议使用 UTF-8
禁用dns查询
server.xml文件中的Connector元素,修改属性enableLookups参数值: enableLookups="false"
如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址
设置sessino过期时间
\web.xml中通过参数指定:
<session-timeout>180</session-timeout>
37.Nginx如何优化
示例
nginx如何优化
worker_processes
nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数
worker_cpu_affinity
为每个进程分配cpu
worker_connections
每个进程允许的最多连接数
keepalive_timeout
会话保持超时时间
worker_rlimit_nofile
nginx 进程打开的最多文件描述符数目,最好与u limit的值保持一致
-
worker_processes 8; nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数 (如,2个四核的cpu计为8)。
-
worker_cpu_affinity 00000001 00000010 为每个进程分配cpu,上例中将8 个进程分配到8 个cpu,当然可以写多个,或者将一个进程分配到多个cpu
-
worker_rlimit_nofile 65535 ;这个指令是指当一个nginx 进程打开的最多文件描述符数目 , 最好与ulimit -n 的值保持一致。
-
use epoll; 使用epoll 的I/O 模型
-
worker_connections 65535; 每个进程允许的最多连接数,
-
keepalive_timeout 60; keepalive 超时时间。
-
client_header_buffer_size 4k; 客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小
-
open_file_cache max=65535 inactive=60s; 这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
-
open_file_cache_valid 80s; 这个是指多长时间检查一次缓存的有效信息。
-
open_file_cache_min_uses 1; open_file_cache 指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。
38.如何统计网站访问量
示例
如何统计网站访问量
第一,分析服务的访问日志,比如使用awk取日志的第一列就是ip 地址,然后使用sort进行排序,然后使用uniq进行去丛,然后使用wc命令的-l选项统计一下行,或者使用awk 的NR变量统计行
第二,用第三方的软件,监控宝等
39.有一个日志文件比较大导致空间沾满,如何快速释放磁盘空间
示例
有一个日志文件比较大导致空间沾满,如何快速释放磁盘空间
将dev下的null导入进文件,可以快速释放磁盘空间
echo > file 或
cat /dev/null > file
40.F S服务器还有空间但是上传不了图片的原因?
示例
F S服务器还有空间但是上传不了图片的原因?
可能节点编号使用完了,可以使用d f命令 -i选项查看节点编号,默认节点编号数量是65535,文件没有内容不占用磁盘空间,但是创建文件占用节点编号
41.常见的raid类型
示例
常见的raid类型
Raid0 没有备份,磁盘任何损坏数据丢失
Raid1 镜像备份,磁盘任何损坏有一份备份,数据不会丢失
Raid5 奇偶校验,使用一块磁盘做校验盘,至少3块盘,最多坏一块盘,使用校验码恢复数据
Raid10 表示对reid1镜像备份做reid0,组合使用
42.软连接和硬链接区别
示例
硬链接:本质是同一个文件,inode相同
软链接:本质不是同一个文件,inode不相同,可以理解为快捷方式
-
本质
- 硬链接:本质是同一个文件
- 软链接:本质不是同一个文件
-
跨设备
- 硬链接:不支持
- 软链接:支持
-
inode
- 硬链接:相同
- 软链接:不同
-
链接数
- 硬链接:创建新的硬链接,链接数会增加,删除硬链接,链接数减少
- 软链接:创建或删除,链接数不会变化
-
文件夹
- 硬链接:不支持
- 软链接:支持
-
相对路径
- 硬链接:原始文件相对路径是相对于当前工作目录
- 软链接:原始文件的相对路径是相对于链接文件的相对路径
-
删除源文件
- 硬链接:只是链接数减一,但链接文件的访问不受影响
- 软链接:链接文件将无法访问
-
文件类型
- 硬链接:和源文件相同
- 软链接:链接文件,和源文件无关
-
文件大小
- 硬链接: 和源文件相同
- 软链接: 源文件的路径的长度
43.有状态和无状态的服务区别
示例
有状态和无状态的服务区别
无状态服务,就是这个应用可以随时重启,然后重启完之后,它产生的一些临时文件,是不需要保存的
有状态服务,需要持久化数据,或者他需要一个固定的标识符
-
无状态请求对于客户端的单次请求的处理,不依赖于其他请求,处理一次请求的信息都包含在请求里,典型的无状态服务的例子就是http 协议。例如,要实现一个计算求和的服务,每次请求都将求和的两个值传送给服务端,然后服务端计算求和结果,并返回给客户端,服务端不保存任何信息,这样的服务就属于无状态服务。
-
有状态服务像mysql主从等
-
Statefulset(是得佛 set)
-
Why(作用):为了解决有状态服务的问题(像mysql主从的,redis集群的这种服务,这种服务是有状态的,这种状态在于比如mysql的master他就一直是mysql的master,这个主从关系是不能谁便换的,如果要换的话有可能导致数据不一致,要是把slave提升为master的话,那么数据都些到slave上去了,mysql结构可能是一主多从的,把数据些到其中一个slave,那别的slave就没数据了,所以说很容易导致这种数据不一致,那则这种服务怎么在k8s里去跑呢?要使用Statefulset控制器才行)
-
What:它所管理的Pod拥有固定的Pod名称,主机名,启停顺序(Statefulset比较特殊,他和Deployment完全不一样,Deployment可以在一个控制器内启动很多容器,这几个容器几乎是没有什么依赖关系的,因为他们的数据要么是单独放在容器里面,要么是通过存储去存储的,并不像mysql需要向主的节点去同步数据,一主多从的mysql一定是从一个master上同步数据的,所以他们有这种很严格的角色关系,这种角色关系是不能随便换的)
-
How(他如何实现):创建一个statefulset类型的pod,并指定serviceName,创建headless类型(headless类型是无头服务他是没有serviceIP的)的svc
-
官方示例: https://kubernetes.io/zh/docs/concepts/workloads/controllers/statefulset/ #后期演示,在早期的时候,我们很难在k8s里面运行这种有状态的服务的像mysql的主从,redis集群等等,是很难实现的,但是有了Statefulset以后就好多了
-
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # 必须匹配 .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # 默认值是 1
minReadySeconds: 10 # 默认值是 0
template:
metadata:
labels:
app: nginx # 必须匹配 .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
# 上述例子中:
# 名为 nginx 的 Headless Service 用来控制网络域名。
# 名为 web 的 StatefulSet 有一个 Spec,它表明将在独立的 3 个 Pod 副本中启动 nginx 容器。
# volumeClaimTemplates 将通过 PersistentVolumes 驱动提供的 PersistentVolumes 来提供稳定的存储。
# StatefulSet 的命名需要遵循DNS 子域名规范。
44.四层和七层负载区别-处理用户请求有什么不同
示例
四层和七层负载区别
四层就是输出层,协议有TCP 和 UDP,主要通过ip地址和端口进行负载均衡
七层就是应用层,协议有HTTP,smtp等,可以通过一些url进行负载均衡
-
所谓4层转发:也就是主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
- 以常见的TCP为例,负载均衡设备在接收到第一个来自客户端的SYN 请求时,即通过上述方式选择一个最佳的服务器,并对报文中目标IP地址进行修改(改为后端服务器IP),直接转发给该服务器。TCP的连接建立,即三次握手是客户端和服务器直接建立的,负载均衡设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。
-
所谓7层负载均衡:也称为“内容交换”,也就是主要通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
- 以常见的TCP为例,负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接受到客户端发送的真正应用层内容的报文,然后再根据该报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。负载均衡设备在这种情况下,更类似于一个代理服务器。负载均衡和前端的客户端以及后端的服务器会分别建立TCP连接。所以从这个技术原理上来看,七层负载均衡明显的对负载均衡设备的要求更高,处理七层的能力也必然会低于四层模式的部署方式
45.常用的负载均衡的软件有哪些,有什么区别?
示例
-
LVS:
- 在lvs/nginx/haproxy当中是性能最强的负载均衡器,尤其是DR模式,⽤⼾的请求经过LVS后转发给real server进⾏相应,但是响应报⽂是web直接通过⽹关进⾏响应,但是没有七层的转发功能,因此在七层的URL判断、域名处理功能都不⽀持,NAT和隧道模式很少使⽤。
-
Haproxy:
- 同时⽀持4层和七层,性能没有LVS强,但是官⽅资料表⽰单机可以承受100W并发,通常可以达到数⼗万并发,通常会使⽤Haproxy 作为4层负载均衡服务器,在访问量较⾼(100W并发以上)会使⽤LVS的DR模式。
-
Nginx:
- 早期只⽀持7层的动静分离,后期(1.9版本)开始⽀持TCP负载功能但是很少使⽤nginx作为4层负载均衡服务器,nginx通常⽤于动态服务(java、PHP、Python)实现动静分离、全站https、以及基于域名的多站点、通过localtion匹配⽤⼾URL进⾏rewrite处理等。
46.Nginx,haproxy,lvs的调度算法(负载均衡策略)
示例
nginx 和 h a proxy 和 l v s的调度算法
l v s
静态算法: r r 轮询,w r r 加权轮询,s h 源地址哈希,d h 目标地址哈希
动态算法: 根据当前负载状态进行调度,l c 使用长连接应用,w l c 默认调度,
haproxy
静态算法: static-r r加权轮询,first第一台服务器的连接数达到上限,新请求才会分配给下一台服务
动态算法: source 源地址哈希
nginx
轮询是默认算法,加权轮询需要定义weight权重,hash 基于u r l做哈希,访问同一个页面,就转发给固定的服务器,ip_hash源地址哈希调度,least_conn最少连接数
-
lvs
-
静态方法仅根据算法本身进行调度
- 1、RR:roundrobin,轮询,较常用
- 2、WRR:Weighted RR,加权轮询,较常用
- 3、SH:Source Hashing,实现session sticky,源IP地址hash;将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现会话绑定
- 4、DH:Destination Hashing;目标地址哈希,第一次轮询调度至RS,后续将发往同一个目标地址的请求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡,如: Web缓存
-
动态方法
- LC:least connections 适用于长连接应用
- WLC:Weighted LC,默认调度方法,较常用
- SED:Shortest Expection Delay,初始连接高权重优先,只检查活动连接,而不考虑非活动连接
- NQ:Never Queue,第一轮均匀分配,后续SED
- LBLC:Locality-Based LC,动态的DH算法,使用场景:根据负载状态实现正向代理,实现Web Cache等
- LBLCR:LBLC with Replication,带复制功能的LBLC,解决LBLC负载不均衡问题,从负载重的复制到负载轻的RS,,实现Web Cache等
-
-
haproxy
-
静态算法
- static-rr:static-rr:基于权重的轮询调度,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制
- first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置
-
动态算法
- roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不完全等于lvs中的rr轮训模式,HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支持4095个realserver,roundrobin为默认调度算法,且支持对real server权重动态调整
- leastconn加权的最少连接的动态,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度(新客戶端连接),比较适合⻓连接的场景使用,比如MySQL等场景
- source 源地址hash,基于用戶源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持/缓存业务等场景
-
-
nginx
- hash KEY consistent;基于指定key做hash计算,使⽤用consistent参数,将使⽤用ketama⼀一致性hash算法,适⽤用于后端是Cache服务器器(如varnish)时使⽤用,consistent定义使⽤用⼀一致性hash运算,⼀一致性hash基于取模运算。 (hash $request_uri consistent)
- ip_hash;#源地址hash调度⽅方法,基于的客户端的remote_addr(源地址)做hash计算,以实现会话保持
- least_conn;#最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器
47.Cookie和session功能是什么?Tomcat session共享怎么做,如何共享
示例
Cookie和session功能是什么?Tomcat session共享怎么做,如何共享
Cookie: 给客户端们颁发一个通行证,数据存放在客户的浏览器上,cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
Session:记录客户状态,数据放在服务器上,通过检查服务器上的“客户明细表”来确认客户身份。考虑到安全应当使用session
使用redis缓存session,共享session
Cookie是服务端返回给客户端字符串,保存于客户端浏览器,是server端在一段时间内保存客户端的信息, 这样客户端使用在有效期内的cookie去访问某网站时,就无需再次登录,以验证客户端身份信息。
-
Cookie是服务端返回给客户端字符串,保存于客户端浏览器,是server端在一段时间内保存客户端的信息, 这样客户端使用在有效期内的cookie去访问某网站时,就无需再次登录,以验证客户端身份信息。
-
Session:服务器保存,用于在多个服务器是被用户
-
共享:redis
48.浏览器输入地址后发生了什么
访问网站的流程
访问网站的流程 ,在浏览器输入地址后首先 dns解析,解析过程最多三个步骤,首先查找本机缓存,然后递归查询,最后迭代查询
通过解析的ip地址与目标服务器建立tcp连接
建立连接后 客户端发送http协议请求
某些服务会做永久丛定向响应
客户端跟踪丛定向地址
服务端处理请求,并返回一个HTML响应
释放tcp连接
客户端收到数据,浏览器进行数据解析和渲染并展示
49.DNS解析过程
示例
DNS解析过程
第一步,浏览器缓存查询
第二步,hosts文件查询
第三步,本地路由器缓存查询
第四步,网络查询,客户端找本地域名服务器查询,这一步是递归查询,本地域名服务器没有结果,那么由本地域名服务器向根域名服务器发起查询请求,这个过程是迭代查询
-
查找浏览器缓存:因为浏览器一般会缓存DNS记录一段时间,不同浏览器的时间可能不一样,一般2-30分钟不等,浏览器去查找这些缓存,如果有缓存,直接返回IP,否则下一步。
-
查找系统缓存:浏览器缓存中找不到IP之后,浏览器会进行系统调用(windows中是gethostbyname),查找本机的hosts文件,如果找到,直接返回IP,否则下一步。
-
查找路由器缓存:如果1,2步都查询无果,则需要借助网络,路由器一般都有自己的DNS缓存,将前面的请求发给路由器,查找ISP 服务商缓存 DNS的服务器,如果查找到IP则直接返回,没有的话继续查找。
-
递归查询:如果以上步骤还找不到,则ISP的DNS服务器就会进行递归查询,所谓递归查询就是如果主机所询问的本地域名服务器不知道被查询域名的IP地址,那么本地域名服务器就以DNS客户的身份,向其他根域名服务器继续发出查询请求报文,而不是让该主机自己进行下一步查询。(本地域名服务器地址是通过DHPC协议获取地址,DHPC是负责分配IP地址的)
- 迭代查询:本地域名服务器采用迭代查询,它先向一个根域名服务器查询。本地域名服务器向根域名服务器的查询一般都是采用迭代查询。所谓迭代查询就是当根域名服务器收到本地域名服务器发出的查询请求报文后,要么告诉本地域名服务器下一步应该查询哪一个域名服务器,然后本地域名服务器自己进行后续的查询。(而不是替代本地域名服务器进行后续查询)。
50.日志收集大概流程
示例
- 我们一般是用logstash取收集java app或网络设备的日志,然后将日志写到kafka,然后又logstash从kafka取出数据,最终logstash根据日志类型做区分后写到es的不同索引中,而且再es前面加了loadbanlace,loadbanlace再去转发到不同的es。这样的话我们再去kibana就可以根据不同的索引查看不同业务的不同日志。
51.Zabbix如何自定义监控项?如何监控mysql,redis?
示例
- 通过shell或python脚本获取监控项的值
- 配置zabbix agent调用脚本获取监控项的数据,并重启zabbix agent
- 在zabbix server使用zabbix get 测试监控项能否获取数据
zabbix_get -s 172.31.0.104 -p 10050 -k "reids_monitor["reids_monitor","6379","bytes"]"
- 在zabbix web创建模板,并在模板中添加监控项,图形,触发器等
- 将模板关联至主机,稍等几分钟,然后验证监控项数据
52.简述osi七层模型,和简述每层的功能
示例
简述osi七层模型,和简述每层的功能
物理层,一些硬件接口,传输的是二进制,比如网卡
数据链路层,一些交换设备,传输的是帧,比如交换机,协议有ppp等
网络层,一些ip选址及路由选择,传输的是数据包,比如路由器,协议有ip ,icmp,arp 等
传输层:传输层为上层协议提供端到端的可靠和透明的数据传输服务,处理差错控制和流量控制等问题。对应的设备如网关,协议有t c p, UDP 等
会话层: 会话层负责管理和协调不同主机上各种进程之间的通信,对应的设备主要是各种服务器和终端设备
表示层,解释数据表示,比如数据加密,压缩等
应用层,比如浏览器这些应用是属于应用层,那么他们背后的协议有http,smtp等
-
物理层(Physical Layer) 物理层规定了激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性以及过程特性。该层为上层协议提供了一个传输数据的物理媒体。
在这一层,数据的单位称为比特(bit)。
属于物理层定义的典型规范代表包括:EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45等。 -
数据链路层(Data Link Layer) 数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。
在这一层,数据的单位称为帧(frame)。
数据链路层协议的代表包括:SDLC、HDLC、PPP、STP、帧中继等。交换机 -
网络层(Network Layer) 网络层负责对子网间的数据包进行路由选择。此外,网络层还可以实现拥塞控制、网际互连等功能。
在这一层,数据的单位称为数据包(packet)。
网络层协议的代表包括:IP、IPX、RIP、OSPF等。路由器 -
传输层(Transport Layer) 传输层是第一个端到端,即主机到主机的层次。传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输。此外,传输层还要处理端到端的差错控制和流量控制问题。
在这一层,数据的单位称为数据段(segment)。
传输层协议的代表包括:TCP、UDP、SPX等。 -
会话层(Session Layer) 会话层管理主机之间的会话进程,即负责建立、管理、终止进程之间的会话。会话层还利用在数据中插入校验点来实现数据的同步。
会话层协议的代表包括:NetBIOS、ZIP(AppleTalk区域信息协议)等。 -
表示层(Presentation Layer) 表示层对上层数据或信息进行变换以保证一个主机应用层信息可以被另一个主机的应用程序理解。表示层的数据转换包括数据的加密、压缩、格式转换等。
表示层协议的代表包括:ASCII、ASN.1、JPEG、MPEG等。 -
应用层(Application Layer) 应用层为操作系统或网络应用程序提供访问网络服务的接口。
应用层协议的代表包括:Telnet、FTP、HTTP、SNMP等
53.Linux启动流程,以及启动级别
示例
Linux启动流程,以及运行级别
第一步,加载BIOS
第二步,读取M B R的引导加载程序
第三步,引导 Linux 内核。
第四步,运行第一个进程 init
第五步,进入相应的运行级别,0是系统停机,1是单用户,2是无网络多用户,3是联网多用户,4是保留,5是图形界面,6是重启
第五步,执行bin目录下的login程序,等待用户登录
-
加载BIOS的硬件信息,获取第一个启动设备
-
读取第一个启动设备MBR的引导加载程序(grub)的启动信息
-
加载核心操作系统的核心信息,核心开始解压缩,并尝试驱动所有的硬件设备
-
核心执行init程序,并获取默认的运行信息
-
init程序执行/etc/rc.d/rc.sysinit文件,重新挂载根文件系统
-
启动核心的外挂模块
-
init执行运行的各个批处理文件(scripts)
-
init执行/etc/rc.d/rc.local
-
执行/bin/login程序,等待用户登录
-
登录之后开始以Shell控制主机
53.进程和线程的区别?
示例
一个进程由一个 或 多个线程组成,线程是一个进程中代码的不同执行路线;
线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
进程之间相互独立
同一进程下的各个线程之间共享程序的内存空间
线程上下文切换比进程上下文切换要快得多
54.描述/etc/fstab文件中每个字段的含义
示例
/dev/mapper/ldl--vg-root / ext4 errors=remount-ro 0 1
描述etc目录下f s tab文件中每个字段的含义
第一段,将被加载的文件系统名或文件系统i d
第二段,文件系统的挂载点
第三段,文件系统的类型
第四段,设置挂载参数,比如auto自动挂载,r o只读,r w可读写等
第五段,值设置为1时,允许dump备份程序进行备份
第六段,在系统引导时检测文件系统的顺序,值为0时,永远不检查,根分区的值永远为1,其他分区从2开始,数字越小越先检查
55.打印 /etc/passwd 的 1 到 3 行
示例
打印 etc目录下passwd 的 1 到 3 行
第一种方式,使用head命令 直接打印前三行
第二种方式,使用sed命令打印1到3行
第三种方式,使用awk命令,然后使用NR变量取范围 NR大于等于1 和 NR小于等于3,然后打印出来
head -n3
sed -n '1,2p' /etc/passwd
awk 'NR>=1&&NR<=3{print $0}' /etc/passwd
56.iptables与fireward区别
示例
-
在RHEL7里有几种防火墙共存:firewalld、iptables、ebtables,默认是使用firewalld来管理netfilter子系统,不过底层调用的命令仍然是iptables等。
-
firewalld跟iptables比起来至少有两大好处:
-
firewalld可以动态修改单条规则,而不需要像iptables那样,在修改了规则后必须得全部刷新才可以生效;
-
firewalld在使用上要比iptables人性化很多,即使不明白“五张表五条链”而且对TCP/IP协议也不理解也可以实现大部分功能。
-
-
firewalld跟iptables比起来,不好的地方是每个服务都需要去设置才能放行,因为默认是拒绝。而iptables里默认是每个服务是允许,需要拒绝的才去限制。
-
firewalld自身并不具备防火墙的功能,而是和iptables一样需要通过内核的netfilter来实现,也就是说firewalld和 iptables一样,他们的作用都是用于维护规则,而真正使用规则干活的是内核的netfilter,只不过firewalld和iptables的结构以及使用方法不一样罢了。
57.tcp与udp的区别
示例
tcp与udp的区别
UDP无连接,类似广播,不保证数据完整,但是快
t c p面向连接,类似电话,需要对方接受,保证数据完整,但是慢
1. TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保 证可靠交付
3. TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
- UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
4. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5. TCP首部开销20字节;UDP的首部开销小,只有8个字节
6. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
- Udp
- 沟通简单,不需要大量的数据结构,处理逻辑和包头字段
- 轻信他人。它不会建立连接,但是会监听这个地方,谁都可以传给它数据,它也可以传给任何人数据,甚至可以同时传给多个人数据。
- 愣头青,做事不懂变通。不会根据网络的情况进行拥塞控制,无论是否丢包,它该怎么发还是怎么发
58.说说常见的状态码,如301等
示例
说说常见的状态码
1开头,是提示信息,表示请求已被成功接收,继续处理
2开头,表示正常响应,服务器端成功的响应的客户端
3开头,表示丛定向
301 永久丛定向
302 临时丛定向
304 资源未修改,浏览器使用本地缓存
4开头,表示客户端请求错误
404 访问了服务器不存在的资源
403 服务器拒绝请求
5开头,表示服务器端错误
500 服务器内部错误,中间没做反向代理直接报500错误
502 上游服务器错误,前面一定有一个反向代理
503 服务器不可访问时给客户端的一种状态
状态码在响应头第一行
1xx提示信息,表示请求已被成功接收,继续处理
2xx表示正常响应 ,服务器端成功的响应的客户端
200 正常返回了网页内容
3xx重定向
301 页面永久性移走,永久重定向。返回新的URL ,浏览器会根据返回的ur1发起新的request请求,这对搜索引擎太重要了,这表示你的网站整体迁移了,搜索引擎看到301马上就要记录下来省的下回指向一个老网站
302 临时重定向,搜索引擎一看临时跳转
304 资源未修改,浏览器使用本地缓存。资源重定向意思是你的资源就不要从我服务器来拿了,你的浏览器的缓存目录里已经有这个图片了就不要找我要了,图片更新有一个时间过期的问题
4xx客户端请求错误
404 Not Found,网页找不到,客户端请求的资源有错,没有资源就是404
400 请求语法错误
401 请求要求身份验证,一发请求就说对不起我这边有验证
403 服务器拒绝请求,你不该访问直接拒绝你不提供服务
5xx服务器端错误
500 服务器内部错误,说明单服务器,这东西往往是java写的Tomcat直接上的那种,中间没做反向反向代理直接报500错误
502 上游服务器错误,例如nginx反向代理的时候就会出现502,很重要,一看就知道这种网站一定是动静分离,前面一定有一个反向代理的
503 访问了服务器不存在的资源,503与404(404 Not Found)是同属一种网页状态出错码。前者是服务器不可访问时给客户端的一种状态,后者是访问了服务器不存在的资源
59.请问当用户反馈网站访问慢,你会如何处理?
示例
请问当用户反馈网站访问慢,你会如何处理
第一步,检查服务器出口带宽
第二步,查看服务器负载
第三步,查看是否数据库瓶颈
第四步,网站代码没优化好
-
分析有哪些方面的因素会导致网站网站访问慢?
-
服务器出口带宽不够用
- 本身服务器购买的出口带宽比较小。一旦并发量大的话,就会造成分给每个用户的出口带宽就小,访问速度自然就会慢。
- 跨运营商网络导致带宽缩减。例如,公司网站放在电信的网络上,那么客户这边对接是长城宽带或联通,这也可能导致带宽的缩减。
-
服务器负载过大,导致响应不过来
- 可以从两个方面入手分析:
- 分析系统负载,使用 w 命令或者 uptime 命令查看系统负载。如果负载很高,则使用 top 命令查看 CPU ,MEM 等占用情况,要么是 CPU 繁忙,要么是内存不够。
- 如果这二者都正常,再去使用 sar 命令分析网卡流量,分析是不是遭到了攻击。一旦分析出问题的原因,采取对应的措施解决,如决定要不要杀死一些进程,或者禁止一些访问等。
-
数据库瓶颈
- 如果慢查询比较多。那么就要开发人员或 DBA 协助进行 SQL 语句的优化。
- 如果数据库响应慢,考虑可以加一个数据库缓存,如 redis 等。然后,也可以搭建 MySQL 主从,一台 MySQL 服务器负责写,其他几台从数据库负责读。
-
网站开发代码没有优化好
-
-
针对网站访问慢,怎么去排查?
-
首先要确定是用户端还是服务端的问题。当接到用户反馈访问慢,那边自己立即访问网站看看,如果自己这边访问快,基本断定是用户端问题,就需要耐心跟客户解释,协助客户解决问题。
- 艿艿:不要上来就看服务端的问题。一定要从源头开始,逐步逐步往下。
-
如果访问也慢,那么可以利用浏览器的调试功能,看看加载那一项数据消耗时间过多,是图片加载慢,还是某些数据加载慢。
-
针对服务器负载情况。查看服务器硬件(网络、CPU、内存)的消耗情况。如果是购买的云主机,比如阿里云,可以登录阿里云平台提供各方面的监控,比如 CPU、内存、带宽的使用情况。
-
如果发现硬件资源消耗都不高,那么就需要通过查日志,比如看看 MySQL慢查询的日志,看看是不是某条 SQL 语句查询慢,导致网站访问慢。
-
-
怎么去解决?
-
如果是出口带宽问题,那么久申请加大出口带宽。
-
如果慢查询比较多,那么就要开发人员或 DBA 协助进行 SQL 语句的优化。
-
如果数据库响应慢,考虑可以加一个数据库缓存,如 redis 等等。然后也可以搭建MySQL 主从,一台 MySQL 服务器负责写,其他几台从数据库负责读。
-
申请购买 CDN 服务,加载用户的访问。
-
如果访问还比较慢,那就需要从整体架构上进行优化咯。做到专角色专用,多台服务器提供同一个服务。
-
60.代码部署上线流程
示例
使用脚本实现对k8s中服务的代码升级和回滚,并且结合jenkins和gitlab
传参使用参数化构建参数,选择选项参数
流程:
第一步,做代码提交
第二步,把代码push到gitlab
第三步,触发jenkins构建,或者自己点击任务构建也行
第四步,构建好镜像之后上传到harbor
第五步,with scripts就是脚本(定义脚本或者pipeline流水线,定义比如
代码拷贝(如果是java代码这里需要执行编译,命令: mvn clean package),
代码打包(将打包好的压缩文件拷贝到k8s 控制端服务器),
构建镜像(到控制端执行脚本,传递变量,制作镜像并上传镜像),
更新yaml文件(到控制端更新k8s yaml文件中的镜像版本号,,从而保持yaml文件中的镜像版本号和k8s中版本号一致),
更新容器版本号(到控制端更新k8s中容器的版本号,有两种更新办法,一是指定镜像版本更新,二是apply执行修改过的yaml文件)
#第一种方法,远程非交互的方式执行kubectl set image更新镜像,指定deployment控制器,指定使用哪个镜像的tag进行更新
ssh root@${K8S_CONTROLLER1} "kubectl set image deployment/helloworld-tomcat-app1-deployment helloworld-tomcat-app1-container=harbor.helloworld.net/helloworld/tomcat-app1:${DATE} -n helloworld"
#第二种方法,推荐使用第一种,远程非交互的方式进入到yaml文件目录下,直接使用apply 更新已经更改过镜像版本号的yaml文件,,加上--record=true参数,完成更新
#ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/yaml/helloworld/tomcat-app1 && kubectl apply -f tomcat-app1.yaml --record=true"
定义回滚,回滚到上一个版本(命令:"kubectl rollout(如喽奥特) undo(安度) deployment/helloworld-tomcat-app1-deployment -n helloworld")
# undo就表示撤销的意思
root@k8s-master1:~# kubectl rollout history deployment/helloworld-tomcat-app1-deployment -n helloworld --revision=2(--revision=选项指定要查看的历史版本)
deployment.apps/helloworld-tomcat-app1-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
# 使用kubectl rollout undo ,这个undo就表示撤销的意思,回到上一个版本,我们现在在2上,只要回到1就可以
root@k8s-master1:~# kubectl rollout undo deployment/helloworld-tomcat-app1-deployment -n helloworld
deployment.apps/helloworld-tomcat-app1-deployment rolled back # deployment.apps/helloworld-tomcat-app1-deployment 回滚
第六步,通过脚本去修改yaml文件,或者去做什么配置等等,比如说创建一个service.yaml文件,这个yaml文件我们之前都是手动写好的,很少在临时通过脚本生成,后续的代码升级都是通过 kubectl set image去更新了
第七步,update ingress更新ingress
# 第一步我们需要部署一个ingress controller负责端口监听,定义监听的端口,必须先部署ingress controller,这个部署也相对比较简单,官方维护了一个github的开源项目,外网可能下不下来,
# 部署ingress controller后,创建yaml文件(可以把这些配置理解为nginx中的service配置)
root@k8s-master1:/opt/Ingress# vim ingress_single-host.yaml
apiVersion: networking.k8s.io/v1 ## 这是他的api版本
kind: Ingress ## 他的类型是Ingress
metadata:
name: nginx-web ## 他的名称是nginx-web
namespace: helloworld # 他的namespace,这个namespace一定要改成和pod和service相同的namespace他不能跨namespace
annotations: ## annotations(注释),这些是类似于参数一样
kubernetes.io/ingress.class: "nginx" ## ingress.class,用于指定Ingress Controller的类型,我们这个是基于nginx的ingress
nginx.ingress.kubernetes.io/use-regex: "true" ## use-regex表示是否使用正则,true表示指定后面rules规则的定义的path可以使用正则表达式去匹配,比如域名
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" ## proxy-connect-timeout表示连接超时时间,默认为5s,修改为了600s
nginx.ingress.kubernetes.io/proxy-send-timeout: "600" ## proxy-send-timeout表示,后端服务器回转数据超时时间,也就是连接到后端服务器之后,后端服务器多长时间乜有接受,那么这个Ingress控制器就认为后端服务器发送数据超时了,这个可能是后端服务器负载比较高,而没有及时接收Ingress的请求,所以就超时了,默认为60s
nginx.ingress.kubernetes.io/proxy-read-timeout: "600" ## proxy-read-timeout表示已经和后端服务器建立好连接了,请求也发送过去了,但是在那么长时间之内没有给我返回数据,可以理解为后端服务器在接收Ingress的请求以后,没有在那么长时间之内返回数据,比如后端程序需要查询数据库,数据库负载比较高,导致数据返回超时,后端服务器响应超时时间,默认为20s
nginx.ingress.kubernetes.io/proxy-body-size: "50m" ## proxy-body-size表示允许客户端上传文件,最大大小,默认为20m
# nginx.ingress.kubernetes.io/rewrite-target: / ## rewrite-target表示是否开启URL重写,就是当用户访问的URL不存在的时候,比如给他转跳掉首页,或者404页面,这个可以开启,也可以不开
nginx.ingress.kubernetes.io/app-root: /index.html ## app-root表示用户在访问网站的时候,如果说他仅是输入了一个域名,后面没有输入比如index.html,那么这里就把URL给他补全,要不然如果没有补全,他可能会报404,请求无法响应
spec:(四百克)
rules: (如肉丝) ## 路由规则,把请求进行匹配,匹配好之后转给某些service中
- host: www.helloworld.net ## 当访问www.helloworld.net这个域名的时候,会匹配这个域名下定义的规则,客户端访问的host域名
http: ## 当访问www.helloworld.net这个域名的时候,以http的方式
paths:
- pathType: Prefix ## Ingress 中的每个路径都需要有对应的路径类型(Path Type),未明确设置 pathType 的路径无法通过合法性检查,当前支持的路径类型有三种:ImplementationSpecific,Exact,Prefix
path: / ## / 表示匹配请求所有路径,表示把www.helloworld.net 这个域名下的所有请求转给指定的service
backend:(白啃得) ## 当访问www.helloworld.net这个域名的时候,以http的方式,转发给这个backend
service: ## 这个backend是一个service要转发给和ingress相同的namespace中的某个app的service,比如tomcat-service或者nginx-service (转发至哪个service)
name: helloworld-nginx-service
port: ## 转发至service的端口号,比如tomcat-service的端口号,所以说这个service就没必要去开nodeport
number: 80
声明式流水线语法
- 声明式的脚本无非就是在它的外层又封装了一层stages(斯带鸡使)
#------------------------------- Dashboard
## 新建任务 (# 点击新建任务)
### 输入一个任务名称
### [ pipeline-test2 ] (# 起一个名称)
### » 该字段不能为空,请输入一个合法的名称
#### 流水线 (# 选择流水线)
##### 确定 (# 点击确定,流水线的界面和自由风格的job稍微有些不一样,里面少了好多菜单)
#------------------------------- pipeline-test2
## 配置
### 流水线
#### 定义
##### [ pipeline script ] (# 选择这个,就是pipeline脚本,先测试一下脚步是否可以执行,然后再选择pipeline script from SCM上传到git)
###### 脚本 (# 把之前脚本式的pipeline改成声明式的)
pipeline{
//agent any // (想在哪个slave节点执行job,就在这里指定,全局必须带有agent,表明此pipeline执行节点,必须要写一个agent 哪怕是any,any就是任何,他会在其中任意一个节点执行job)
agent { label 'jenkins-slave1' } // (或者就写agent然后label根据节点标签jenkins-slave1,把他调度到哪个节点去执行,这是全局的。)
stages(斯带鸡使){
stage(斯带鸡)("代码clone"){
//#agent { label 'jenkins-master' } //具体执行的步骤节点,非必须 (甚至你可以让你的pipeline哪个阶段,在哪个节点上去执行,也可以这么细分)
steps(斯带普斯){
sh "cd /var/lib/jenkins/workspace/pipeline-test2 && rm -rf ./*" // (这里不用删除了,他会自动清理目录,但是我们要切换到这个目录下,克隆代码)
git branch: 'develop', credentialsId: 'a59287ed-6063-44f4-a730-5da9c70fb1fa', url: 'git@10.0.0.3:helloworld/web1.git' // 这里填入通过流程线语法生成的克隆语句
echo "代码 clone完成"
}
}
stage("代码构建"){ // (代码构建无非就是打个包)
steps{
sh "cd /var/lib/jenkins/workspace/pipeline-test2/ && tar czvf myapp.tar.gz ./index.html"
}
}
代码自动化上线流程
# 创建脚本
root@jenkins-master:/data/scripts# vi helloworld-tomcat-app1-deploy.sh
#!/bin/bash
#Author: helloworld
#Date: 2019-08-03
#Version: v1
#记录脚本开始执行时间,后面可能会统计一下部署一共花了多长时间
starttime=`date +'%Y-%m-%d %H:%M:%S'`
#变量
## 脚本路径
SHELL_DIR="/root/scripts"
## 脚本名称
SHELL_NAME="$0"
## k8s集群1(master地址,由于构建镜像,镜像服务器使用共享存储,共享同一份数据,挂了一台也没事,但是脚本这里需要做好测试,这个脚步没有测试服务器可用性)
K8S_CONTROLLER1="10.0.0.3"
## k8s集群2(master地址)
K8S_CONTROLLER2="10.0.0.4"
## k8s集群3(master地址)
K8S_CONTROLLER2="10.0.0.5"
## 定义时间戳,这个时间戳主要是用来修改镜像的tag
DATE=`date +%Y-%m-%d_%H_%M_%S`
## 主分支(生产分支)
METHOD=$1
## 开发分支(测试分支)
Branch=$2
## 如果没有写分支,那么默认就是开发分支
if test -z $Branch;then
Branch=develop
fi
function Code_Clone(){
## git的克隆地址
Git_URL="git@10.0.0.4:helloworld/app1.git"
## 目录名称,主要是获取app1这个项目的名称
DIR_NAME=`echo ${Git_URL} |awk -F "/" '{print $2}' | awk -F "." '{print $1}'`
## 定义目录,此目录没有需要创建出来,这个目录其实就是我们项目的名称,因为我们这个项目有好多服务,所以同一个项目中的服务代码一定要克隆到同一块,我们这个项目可能会有app1,app2那么他们的代码如果都是helloworld这个项目的,那么都放在/data/gitdata/helloworld下的app1是第一个项目,app2是第二个项目
DATA_DIR="/data/gitdata/helloworld"
## 把/data/gitdata/helloworld这个变量和app1变量做了拼接
Git_Dir="${DATA_DIR}/${DIR_NAME}"
## 删除上一个版本的代码,如果克隆的时候有上一个版本的代码,是无法克隆成功的,所以需要先删除了
cd ${DATA_DIR} && echo "即将清空上一版本代码并获取当前分支最新代码" && sleep 1 && rm -rf ${DIR_NAME}
echo "即将开始从分支${Branch} 获取代码" && sleep 1
## 删除完上一个版本的代码,开始克隆代码
git clone -b ${Branch} ${Git_URL}
echo "分支${Branch} 克隆完成,即将进行代码编译!" && sleep 1
## 如果是java代码,这个地方可能需要执行编译,这里不编译所以注释掉
#cd ${Git_Dir} && mvn clean package
#echo "代码编译完成,即将开始将IP地址等信息替换为测试环境"
#####################################################
sleep 1
## 切换到代码目录
cd ${Git_Dir}
## 在代码目录打个包,会把代码打包成app1.tar.gz
tar czf ${DIR_NAME}.tar.gz ./*
}
# 将打包好的压缩文件拷贝到k8s 控制端服务器
function Copy_File(){
echo "压缩文件打包完成,即将拷贝到k8s 控制端服务器${K8S_CONTROLLER1}" && sleep 1
## 把app1.tar.gz这个压缩包,拷贝到K8S_CONTROLLER1也就是master1服务器上打包镜像,注意打包镜像的路径,所以还需要做好免秘钥认
证,拷贝的时候以非交互的方式把代码包,拷贝到规划好的目录下
scp ${Git_Dir}/${DIR_NAME}.tar.gz root@${K8S_CONTROLLER1}:/opt/k8s-data/dockerfile/helloworld/tomcat-app1/
echo "压缩文件拷贝完成,服务器${K8S_CONTROLLER1}即将开始制作Docker 镜像!" && sleep 1
}
# 到控制端执行脚本,传递变量,制作镜像并上传镜像
function Make_Image(){
## 以非交互的方式连接到K8S_CONTROLLER1中执行build-command.sh脚本,并传递DATE变量,这样这个时间戳就相当于远程传递过去了
echo "开始制作Docker镜像并上传到Harbor服务器" && sleep 1
ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/dockerfile/helloworld/tomcat-app1 && bash build-command.sh ${DATE}"
echo "Docker镜像制作完成并已经上传到harbor服务器" && sleep 1
}
# 到控制端更新k8s yaml文件中的镜像版本号,,从而保持yaml文件中的镜像版本号和k8s中版本号一致
function Update_k8s_yaml(){
echo "即将更新k8s yaml文件中镜像版本" && sleep 1
echo "k8s yaml文件镜像版本更新完成,即将开始更新容器中镜像版本" && sleep 1
}
# 到控制端更新k8s中容器的版本号,有两种更新办法,一是指定镜像版本更新,二是apply执行修改过的yaml文件
function Update_k8s_container(){
#第一种方法,远程非交互的方式执行kubectl set image更新镜像
echo "k8s 镜像更新完成" && sleep 1
echo "当前业务镜像版本: harbor.helloworld.net/helloworld/tomcat-app1:${DATE}"
#计算脚本累计执行时间,如果不需要的话可以去掉下面四行
endtime=`date +'%Y-%m-%d %H:%M:%S'`
# 时间戳转换成秒
start_seconds=$(date --date="$starttime" +%s);
# 时间戳转换成秒
end_seconds=$(date --date="$endtime" +%s);
# 最后计算一下,拿end_seconds去减掉start_seconds,主要是为了计算一下本次升级一共花了多长时间
echo "本次业务镜像更新总计耗时:"$((end_seconds-start_seconds))"s"
}
# 基于k8s 内置版本管理回滚到上一个版本
functioNRollback_last_version(){
echo "即将回滚之上一个版本"
# 这里远程非交互到管理节点执行kubectl rollout undo回滚到上一个版本
ssh root@${K8S_CONTROLLER1} "kubectl rollout undo deployment/helloworld-tomcat-app1-deployment -n helloworld"
sleep 1
echo "已执行回滚至上一个版本"
}
#使用帮助
usage(){
echo "部署使用方法为 ${SHELL_DIR}/${SHELL_NAME} deploy "
echo "回滚到上一版本使用方法为 ${SHELL_DIR}/${SHELL_NAME} rollback_last_version"
}
#主函数(这个脚本要一点一点写,把函数先注释掉,从第一个Code_Clone代码克隆函数开始,一个函数,一个函数测试)
main(){
case ${METHOD} in
deploy)
Code_Clone;
# Copy_File;
# Make_Image;
# Update_k8s_yaml;
# Update_k8s_container;
;;
rollback_last_version)
rollback_last_version;
;;
*)
usage;
esac;
}
main $1 $2
61.系统io模型
示例
系统io模型
同步: 调用者主动询问内核事情是否处理完成
异步: 内核主动返回状态给调用者
阻塞: 结果返回之前,调用者被挂起,⼲不了别的事情
⾮阻塞: 结果返回之前,调用者被挂起,⼲不了别的事情
62.nginx常用模型
示例
nginx常用模型
select:
poll:
epoll:异步非阻塞
1.问:主要是跑什么业务
2.问:Master也可以调度服务是吗
3.问:Etcd数据的备份是怎么做的
示例
-
etcd在每一次真正写入数据之前,都是写入一个日志,也叫做预写日志,记录了数据变化的全部过程,我们备份的就是这个预写日志文件,在进行重放,备份使用etcdctl snapshot save 跟上要创建的文件名称,还原使用etcdctl snapshot restore 跟上备份的文件名称,使用--data--dir指定还原到哪个路径下
-
万一那天忘记备份了,我们可以把备份命令写到脚本中,使用计划任务每天晚上2点或者3点执行一下。
-
etcd数据恢复流程有两种情况
- (集群宕机数量超过集群数量的一半以上,比如3台etcd,宕机2台,会导致集群宕机)
-
先恢复服务器,然后重新部署etcd,停止k8s集群,停止etcd集群,各etcd节点恢复同一份备份数据,然后启动各节点验证etcd集群,启动k8s集群,验证k8s集群状态
-
验证etcd集群心跳,使用etcdctl endpoint health --endpoints 指定https协议跟上节点ip加上2379端口号,然后使用参数跟上证书
-
- (集群宕机数量超过集群数量的一半以上,比如3台etcd,宕机2台,会导致集群宕机)
4.问:安装的k8s版本是多少
4.1 问:安装的docker版本是多少
4.2 问:harbor的版本
5.问:测试生产都是一样的吗(版本)
6.问:master默认是不可调度服务的,怎么设置污点
示例
master默认是不可调度服务的,怎么设置污点
使用taint命令设置污点,污点级别是No Schedule不能调度,不驱逐已部署的 和 No Execute,不能被调度,驱逐已部署的 和 Pre fer No Schedule,尽量不调度
-
默认master节点仅作为控制节点,pod部署在node节点上,如果你像在master节点上部署pod执行以下命令
-
污点策略
- NoSchedule :一定不能被调度。
- PreferNoSchedule:尽量不要调度。
- NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。
# 去除污点
kubectl taint nodes --all node-role.kubernetes.io/master-
## 或者
kubectl taint nodes --all node-role.kubernetes.io/master:NoSchedule-
# 设置污点
kubectl taint nodes --all node-role.kubernetes.io/master:NoSchedule
# taint 给node标记污点,实现反亲pod与node反亲和性(打上污点之后,就不会在这个节点执行调度了)
# nodes 表示对node执行操作
# --all 表示选择集群中的所有节点(也可以指定节点名称)
# node-role.kubernetes.io/master- 表示在所有节点中,带有node-role.kubernetes.io/master这个key,“-” 横-表示去除污点,NoSchedule 可以省略
7.问:我现在有三个work节点,其中一个work节点出问题了,怎么把这个节点设置成为不可调度服务,然后维修这个节点
示例
我现在有三个work节点,其中一个work节点出问题了,怎么把这个节点设置成为不可调度服务,然后维修这个节点
节点下线使用drain 命令,他通过一些迁移策略将pode从节点迁移出去,比如需不需要保留本地数据,比如d s控制器启动的容器要不要迁移走,因为drain是给节点打了一个un schedulable标签,d s容忍了这个标签,最后停机下线维护好后,节点上线后需要使用un cordon 去掉节点的这个污点
# 删除节点
# 首先将节点设置为不可调度,使用kubectl 使用drain选择,加上节点名称 跟上要使用的参数,等待节点上的pod销毁,重建完成后,使用kubectl delete node 删除节点
# 添加节点
# 修复后在使用创建节点的方式添加节点
8.问:如何查看pod跑在哪个机器上,他的ip是什么,什么是什么可以查出来
示例
如何查看pod跑在哪个机器上,他的ip是什么
使用-o wide显示详细的信息,包括pode所在的节点和ip地址
9.问: 起三个pod,然后这三个pod要调度到三个不同的node节点上,如何设置(三个同样的服务,三个副本数,跑在不同的节点上)
示例
起三个pod,然后这三个pod要调度到三个不同的node节点上,如何设置
将三个副本pode调度到三个不同的节点上,需要使用Affinity亲和力,定义replicas副本数是三个,然后定义Affinity亲和力,使用pode反亲和,使用硬亲和,然后匹配pode的key和value,匹配方式是in,然后定义topologyKey范围是标签key是hostname的节点主机,当在节点匹配到key和value相同的容器,由于是pode反亲和,就不会在此节点在创建pode,从而实现把三个pode调度到不同的node节点上
- 定义副本
# 他的coredns副本未指定,默认副本数是1,如果要开启多个副本数,添加replicas参数,指定要启动的服务数即可
# replicas: 2
- DaemonSet 在当前集群中每个节点运行同一个pod(是同一个类型的pod,node节点上有,master节点上也有),当有新的节点加入集群时也会为新的节点配置相同的pod(他其实就是在所有的k8s集群节点上去运行相同功能的一个pod,如果服务被设置为DaemonSet,那么在每一个服务器上都会运行同一个pod,这种比较适合于日志收集,在每一个服务器起一个容器去收集宿主机上的一些日志,那么要么在服务器上手动去配置一个服务使用systemd去启动,或者说使用去管理更简单,更省事,只是第一次需要写个yaml文件),当节点从集群中移除时其pod也会被kubernetes回收(而不会影响别的节点的pod),但是删除DaemonSet控制器 将删除其创建的所有的pod。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ssd-monitor
namespace: custom2
labels:
k8s-app: ssd-monitor
spec:
selector:
matchLabels:
app: ssd-monitor
template:
metadata:
labels:
app: ssd-monitor
spec:
# tolerations:
# this toleration is to have the daemonset runnable on master nodes
# remove it if your masters can't run pods
# - key: node-role.kubernetes.io/master
# effect: NoSchedule
containers:
- name: ssd-monitor
image: luksa/ssd-monitor
nodeSelector(node死来可特尔):
disk: ssd # 你正在定义一个DaemonSet,它将运行一个基于luksa/ssd-monitor容器镜像的单容器pod。该pod的实例将在每个具有disk=ssd标签的节点上创建。
- 自定义node label
# 使用kubectl label给10.0.0.13这个node添加一个标签,然后标签是一个键值对儿数据,可以自己定义,但是键不要冲突了,比如键是project,表示项目,值是helloworld,表示helloworld这个项目
root@k8s-master1:~# kubectl label node 10.0.0.13 project=helloworld
node/10.0.0.13 labeled # 节点/10.0.0.13 标记
- 删除自定义node label
# 使用kubectl label 指定node资源,在192.168.7.110这个node上,把标签的key后面添加一个 - 横-,就把这个标签删除了
root@k8s-master1:~# kubectl label nodes 10.0.0.13 project-
11.问:需要指定一下docker本身镜像存储的路径,需要怎么配置
示例
镜像默认存储在var目录的lib目录下的docker
通过修改daemon点json文件修改data-root指定自定义目录
15.问:现在有一个集群需要配置一个harbor,如何配置
示例
现在有一个集群需要配置一个harbor,如何配置
harbor的部署比较简单,需要docker环境,需要通过docker-compose部署,一般配置文件需要关注主机名称是什么,数据存储路径,管理员密码,h t t p s等,有需要可以配置为高可用
16.问:harbor启动的有问题,先停止在启动,是如何操作的
示例
harbor启动的有问题,先停止在启动,是如何操作的
先使用docker compose的down停止并删除资源,然后使用up创建并启动容器
17.问:harbor镜像的同步有做过吗(生产 和测试 场景是网络隔离的,测试一个harbor,生产一个harbor ,这两个镜像如何同步过去)
示例
harbor镜像的同步有做过吗
在仓库管理中新建目标,填写要同步的目标,确保测试连接是成功的,然后在复制管理中新建规则,复制模式有两种,一种是Push上传到远端,一种是pull下载到本地,出发模式可以是事件启动,也就是上传和删除镜像操作时和远端同步
18.问:k8s的升级操作做过吗(替换了哪几个文件,执行了哪几个命令)
示例
k8s的升级操作做过吗
升级必须反复测试,对于etcd升级,最后升级主节点.停机服务直接替换二进制包,然后启动,如果启动不成功,可能服务配置有改动,对于k8s升级,Master节点一个节点一个节点升级,替换apiservice,controller manager和scheduler和proxy的二进制包,如果不成功可能配置文件有变动,node和calico升级,下载指定版本calico的yaml文件,修改网络配置,将更新策略修改为OnDelete进行升级,node节点需要使用drain命令驱逐pode进行替换二进制文件,进行升级,完成后使用un cordon 清理节点上的污点,CoreDNS下载指定版本CoreDNS的yaml文件,修改配置直接更新创建
19.问:证书是有时间限制的,时间到期了如何续租
示例
20.问:现在要部署一个nginx服务,然后这个nginx服务的配置文件做持久化存储,然后启动三个副本数,把服务暴露出来,这种是怎么配置的
示例
现在要部署一个nginx服务,然后这个nginx服务的配置文件做持久化存储,然后启动三个副本数,把服务暴露出来,这种是怎么配置的
把n nginx的配置文件创建configmap来持久化存储,至于配置文件的来源,可以从容器内导出,然后定义replicas定义副本数,通过service定义为nodeport把服务暴露出来
21.问:设置副本数为3个的参数是什么
示例
replicas
22.问:把服务布置好了,然后需要把这个服务提供出来访问,那么访问方式有几种
示例
把服务布置好了,然后需要把这个服务提供出来访问,那么访问方式有几种
可以使用NodePort 或者 ingress来提供访问
-
ClusterIP
- 默认的类型,用于k8s内部之间的服务访问,即通过内部的service ip 实现服务间的访问,service ip仅可以在内部访问,没有nodeport端口不能从外部访问
-
比如通过yaml文件创建的service在没有指定type类型的情况下,他默认其实就是一个ClusterIP
-
表示集群id只在k8s内部使用,比如nginx调用tomcat这个类型可以理解他就是一个ClusterIP只在k8s内部访问,不能同宿主机以外的网络去访问,因为在宿主机以外没有给他开端口,没有端口就访问不了
-
- 默认的类型,用于k8s内部之间的服务访问,即通过内部的service ip 实现服务间的访问,service ip仅可以在内部访问,没有nodeport端口不能从外部访问
-
NodePort
- 在cluster ip的基础之上,通过在每个node节点监听一个可以指定宿主机端口(NodePort)来暴露服务,从而允许外部client访问k8s集群中的服务,nodePort把外部client的请求转发至service进行处理
-
他其实也会创建一个cluster ip只不过把type类型指定为NodePort之后,他会在宿主机启用我们给他指定的nodeport端口号,把访问这个端口号的请求,转发给这个service,当然可以把这个转发定义为iptables规则,或者是ipvs规则都可以,查看规则,请求访问宿主机的暴露的NodePort端口,然后转发给service的ip地址,类似于虚拟ip一样,然后他后面就是那些pod了,所以说我们把service当做k8s内部的负载均衡器,这个规则是有kube-proxy通过kube-apiserver去etcd拿到pod创建的时候那些端口的绑定事件,然后调用内核去创建service,所以这些service我们也不需要动,是有kube-proxy来维护,而且即便把iptables修改为了ipvs之后,他依然会有很多iptabes规则,这些规则我们也不需要动,也是有kube-proxy维护的,我们的service是使用的ipvs,但是docker还是会产生很多iptables
-
表示如果说服务想通过宿主机以外的端口去访问那么一定要在k8s内部的宿主机上给他开个端口,这个端口可以把你的请求通过这个端口转发给你相应的pod,那么这个就是NodePort,比如就跟nginx一样,这个nginx为什么能从外部访问,就是因为给他开了NodePort这个NodePort是32004,在访问这个端口的时候会转发给和他相对应的nginx-service,然后nginx-service在基于labels标签筛选找到后端的pod,就是ngixn所以这个时候你的请求就被nginx-service转发给nginx的容器上去了
-
- 在cluster ip的基础之上,通过在每个node节点监听一个可以指定宿主机端口(NodePort)来暴露服务,从而允许外部client访问k8s集群中的服务,nodePort把外部client的请求转发至service进行处理
-
LoadBalancer
- 主要在共有云如阿里云,AWS上使用,LoadBalancer构建在nodePort基础之上,通过公有云服务商提供的负载均衡器将k8s集群中的服务暴露给集群外部的client访问
-
这个在公有云上会用,比如阿里云或者AWS,或者谷歌云,可以把外部的某个负载均衡器上的地址给他导入进来,其实就是这个负载均衡器不是我们自己安装的而是公有云上的负载均衡器,这里类型可以定义把某个service定义为互联网上的这种有公有云提供的负载均衡器
-
他对AWS的兼容性最好,对阿里云的兼容不太好,LoadBalancer是在ClusterIP的NodePort基础之上有起了LoadBalancer,这样可以直接把公有云的一个LB,和nodeport进行一个绑定,然后把域名解析到这个LB,就可以访问k8s其中的服务,就类似于安装一个haproxy,或者安装一个nginx,然后去修改他的配置文件,把这个请求转给哪个哪个nodeport端口一样
-
- 主要在共有云如阿里云,AWS上使用,LoadBalancer构建在nodePort基础之上,通过公有云服务商提供的负载均衡器将k8s集群中的服务暴露给集群外部的client访问
-
ExternalName
- 用于将k8s集群外部的服务映射至k8s集群内部访问,从而让集群内部的pod能够通过固定的service name访问集群外部的服务,有时候也用于将不同namespace之间的pod通过ExternalName进行访问
-
表示把外部的一些服务暴露在k8s内部去,在内部使用,比如k8s外部有一个数据库,我们需要在k8s内部通过这种service名称去访问k8s集群以外的这个服务,这个时候就可以定义一个service把k8s集群以外的服务给他起一个service名称,这个时候访问这个名称,就会被转发给这个服务器,这种情况下我们用的不是特别多
- 将k8s集群外部的某些服务映射到k8s集群内部供k8s中的某些app,通过service name的方式去访问web的服务,web的服务比如数据库,kafka等,这些服务,他可能是个地址,这个地址以后可能会变,所以说我们在k8s内部给他定义一个域名,我们k8s内部的app在访问的时候,就可以通过固定的域名去访问Service如果是cluster类型,那么从clusterIP到pod是默认的TCP协议,TCP支持MySQL,redis等特定服务,另外还有UDP和SCTP协议比如从tomcat-service到后面的tomcat-app1,tomcat-app2这段,一般使用的是TCP
-
- 用于将k8s集群外部的服务映射至k8s集群内部访问,从而让集群内部的pod能够通过固定的service name访问集群外部的服务,有时候也用于将不同namespace之间的pod通过ExternalName进行访问
-
ingress
- 还有一个是ingress,这个ingress和NodePort的区别在于,ingress基于七层,应用层,可以实现类似于nginx的七层代理与https等功能,可以理解他其实就是一个基于k8s提供配置的一个七层反向代理负载均衡器,他用来替代nginx这个位置,如果有了ingress的话,那么这个nginx就不需要了,所以说需要把nginx中配置的location 也好,包括upstream 配置的server也好通通配置在ingress里面,让ingress把请求在转发给我们指定的service,包括Envoy+Istio也是在这个位置
23.问:service和deployment怎么就可以通信了
示例
service和deployment怎么就可以通信了
service没有和Deployment关联上,而是和Deployment管理的pode通过标签选择器关联上了
1.问:什么环境可以描述一下吗,生产环境,测试环境,大概跑的量,和服务器的配置大概描述一下
示例
2.问:calico的BGP说一下。calico的几种网络模式,各自都是什么原理,优势是啥说一下
示例
calico的几种网络模式,各自都是什么原理
IP in IP叠加模型,简称ip ip,可以实现跨不同网段建立路由通信,是将各Node节点的路由之间做一个tunnel(隧道),再把两个网络连接起来的模式。启用ip ip模式时,Calico将在各Node上创建一个名为"tunl0"的虚拟网络接口,这其实是一个隧道。报文出去之后,会被隧道封装一次,容器的源地址会被替换为宿主机的,通过宿主机地址在出去,因为不同子网通信,需要经过路由器做路由寻址,路由器只能识别到宿主机的地址,路由器可不知道容器地址是多少,可以通过Calico的配置文件设置是否启用ip ip,在公司内部如果k8s的node节点没有跨越网段,建议关闭ip ip。
BGP 是边界网关协议,一个去中心化的协议,通过自动学习路由规则并在node节点生成路由规则,从而将不同node节点上的pode连接起来进行通信。他直接使用物理机作为虚拟路由路,不再创建额外的tunnel。也就是如果关闭ip ip,他会直接使用物理网卡转发报文,把报文直接转给宿主机的物理网卡,然后把报文解封之后再有内核直接交给容器,缺点node无法自动跨子网通信,并且并不是所有的网络都支持BGP(比如公网,阿里云他就不支持BGP,那么calico的路由表学习不成功,就跑不起来无法实现pod的跨主机通信)
3.问: 主要的是跑什么业务
示例
CRM
一百多台服务器(node)
业务量
学员生命周期管理,一整套,你把它说清楚,就是整个业务了,业务推广,拉新
4.问:pod终止过程说一下
示例
- 因为Pod作为在集群的节点上运行的进程,所以在不再需要的时候能够优雅的终止掉是十分必要的(比起使用发送KILL信号这种暴力的方式)。用户需要能够放松删除请求,并且知道它们何时会被终止,是否被正确的删除。用户想终止程序时发送删除pod的请求,在pod可以被强制删除前会有一个宽限期,会发送一个TERM请求到每个容器的主进程。一旦超时,将向主进程发送KILL信号并从API server中删除。如果kubelet或者container manager在等待进程终止的过程中重启,在重启后仍然会重试完整的宽限期。-
终止过程主要分为如下几个步骤:
-
用户发送删除pod的命令,默认宽限期是30秒;
-
在Pod超过该宽限期后API server就会更新Pod的状态为“dead”;
-
在客户端命令行上显示的Pod状态为“terminating”;
-
跟第三步同时,当kubelet发现pod被标记为“terminating”状态时,开始停止pod进程:
- 如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在运行,第二步会再增加2秒的宽限期;
- 向Pod中的进程发送TERM信号;
-
跟第三步同时,该Pod将从该service的端点列表中删除,不再是replication controller的一部分。关闭的慢的pod将继续处理load balancer转发的流量;
-
过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号从而杀掉进程。
-
Kublete会在API server中完成Pod的的删除,通过将优雅周期设置为0(立即删除)。Pod在API中消失,并且在客户端也不可见。
-
-
删除宽限期默认是30秒。 kubectl delete命令支持 —grace-period=
选项,允许用户设置自己的宽限期。如果设置为0将强制删除pod。在kubectl>=1.5版本的命令中,你必须同时使用 --force 和 --grace-period=0 来强制删除pod。 -
Pod的强制删除是通过在集群和etcd中将其定义为删除状态。当执行强制删除命令时,API server不会等待该pod所运行在节点上的kubelet确认,就会立即将该pod从API server中移除,这时就可以创建跟原pod同名的pod了。这时,在节点上的pod会被立即设置为terminating状态,不过在被强制删除之
5. log stash这个组件具体是干什么的,实现什么功能说一下
示例
- Logstash 是一个具有实时传输能力的数据收集引擎,可以通过插件实现日志收集和转发,支持日志过滤,比如filter插件,是添加在input和output中间的,最终把经过处理的日志发送给 elasticsearch。
input {
redis {
data_type => "list"
key => "helloworld-nginx-syslog"
host => "10.0.0.11"
port => "6379"
db => "0"
password => "12345678"
}
filter {
# 先进行判断只有这个日志是什么日志类型的情况,我们才会对他进行匹配过滤,所以这个地方也会加判断
if [fields][project] == "helloworld-nginx-accesslog" {
# 如果条件成立了,使用geoip模块,匹配这些信息
geoip {
# source表示你要匹配哪些信息,是来自于日志中的clientip字段,clientip的key是远端访问我这网站的客户端ip地址,所以这个格式必须是json,通过json格式日志中的clientip取到值
source => "clientip"
# 取得值之后,通过geoip模块在匹配
target => "geoip"
# 指定我们的地址库路径,所以说他是使用的是本地的文件
database => "/etc/logstash/GeoLite2-City_20210831/GeoLite2-City.mmdb"
# 这个geoip模块需要在你的每条日志中添加字段,添加经纬度,这个经纬度会通过GeoLite2-City.mmdb这个地址模块,匹配出clientip的值,他是哪个城市,这个城市有一个坐标,这个坐标就是经纬度,所以说他把这个%{[geoip][latitude]}经纬度信息自动添加上去,通过这个经纬度我们就能匹配出他是哪个城市了,包括在地球哪个地方他都给你匹配出来
add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ]
add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ]
}
mutate {
# 这里还有一个格式转换,把这个地址库信息转换成float也就是浮点数,转换成浮点数之后我们就可以在地图上显示了
convert => [ "[geoip][coordinates]", "float"]
}
}
}
# input是一个输入源,那么输入源里面一共有哪些模块,他可以有好多输入,标准输入只是其中一个而已,可以是文件,可以是redis,可以是kafka等等
input {
stdin{}
}
# output是一个输出,输出到什么地方
output{
stdout{}
}
6. flannel几种网络模式说一下,说一下flannel的Host Gate Way模式 和 calico的BGP模式啥区别说一下
示例
flannel几种网络模式说一下
Flannel目前有三种方式 UDP 和 VXLAN 和 hostgw:
UDP:早期版本的Flannel使用UDP封装,完成报文的跨越主机转发,其安全性以及性能略有不足。
VXLAN:本质上是一种tunnel(隧道)协议,用来基于三层网络实现虚拟的2层网络(意思就是把mac地址封装在三层网络层报文之内,然后发送到对端的主机之后,再把报文拆封装,从而拿到封装在报文中的mac地址,在通过这个mac地址对访问对端的容器),目前flannel 的网络模型已经是基于VXLAN的叠加网络,目前推荐使用VXLAN作为其网络模型。
hostgw:也就是Host GateWay,通过在node节点上创建到达各目标容器地址的路由表而完成报文的转发,因此这种方式要求各node节点本身必须处于同一个局域网(二层网络)中(不能跨网段,因为他转发是依赖mac地址的,性能很强和calico的BGP差不多,毕竟他们都是在同一个二层网络转发的),因此不适用于“网络变动频繁或比较大型的网络环境”,但是其性能较好。
7. 创建pod的流程,各组件都起啥作用说一下
示例
创建pod的流程,各组件都起啥作用说一下
用户通过kubectl命名发起请求。
apiserver通过对应的kubeconfig进行认证,认证通过后将yaml中的pode信息存到etcd。
Controller-Manager通过apiserver的watch接口发现了pode信息的更新,执行该资源所依赖的拓扑结构整合,整合后将对应的信息交给apiserver,apiserver写到etcd,此时pode已经可以被调度了。
Scheduler同样通过apiserver的watch接口更新到pode可以被调度,通过算法给pode分配节点,并将pod和对应节点绑定的信息交给apiserver,apiserver写到etcd,然后将pode交给kubelet。
kubelet收到pode后,调用CNI接口给pode创建pode网络,调用CRI接口去启动容器,调用CSI进行存储卷的挂载。
网络,容器,存储创建完成后pode创建完成,等业务进程启动后,pode运行成功。
第一步:kubectl create pod
首先进行认证后,kubectl会调用master api创建对象的接口,然后向k8s apiserver发出创建pod的命令
第二步:k8s apiserver
apiserver收到请求后,并非直接创建pod,而是先创建一个包含pod创建信息的yaml文件,并将文件信息写入到etcd中(如果此处是用yaml文件创建pod,则这两步就可以忽略)
第三步:controller manager
创建Pod的yaml信息会交给controller manager ,controller manager根据配置信息将要创建的资源对象(pod)放到等待队列中。
第四步:scheduler
scheduler 查看 k8s api ,类似于通知机制。首先判断:pod.spec.Node == null?
若为null,表示这个Pod请求是新来的,需要创建;然后进行预选调度和优选调度计算,找到最“闲”的且符合调度条件的node。最后将信息在etcd数据库中更新分配结果:pod.spec.Node = node2(设置一个具体的节点)同样上述操作的各种信息也要写到etcd数据库中。
分配过程需要两层调度:预选调度和优选调度
(1)预选调度:一般根据资源对象的配置信息进行筛选。例如NodeSelector、HostSelector和节点亲和性等。
(2)优选调度:根据资源对象需要的资源和node节点资源的使用情况,为每个节点打分,然后选出最优的节点创建资源对象(pod)。
第四步:kubelet
目标节点node2上的kubelet进程通过API Server,查看etcd数据库(kubelet通过API Server的WATCH接口监听Pod信息,如果监听到新的pod副本被调度绑定到本节点)监听到kube-scheduler产生的Pod绑定事件后获取对应的Pod清单,然后调用node1本机中的docker api初始化volume、分配IP、下载image镜像,创建容器并启动服务
第五步:controller manager
controller manager会通过API Server提供的接口实时监控资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试将其状态修复到“期望状态”
8. k8s 1.23版本以后不支持docker了,都用containerd了。说说这两种有啥区别说一下
示例
k8s 1.23版本以后不支持docker了,都用containerd了。说说这两种有啥区别说一下
从k8s的角度看,可以选择 containerd 或 docker 作为运行时
docker调用链长,kubelet使用自身docker shim程序去调用dockerd在调用containerd
Containerd调用链短,kubelet使用自身criplugin程序直接调用containerd
k8s 1.23版本kubelet以后不支持docker shim程序
9. 容器 (即pod) 生命周期
示例
-
(pod)容器生命周期的几种行为
-
初始化容器
- 初始化容器即pod内主容器启动之前要运行的容器,主要是做一些前置工作,初始化容器具有一下特征:
- 初始化容器必须首先执行,若初始化容器运行失败,集群会一直重启初始化容器直至完成,注意,如果pod的重启策略为Never,那初始化容器启动失败后就不会重启
- 初始化容器必须按照定义的顺序执行,初始化容器可以通过pod的spec.initContainers进行定义。
- 初始化容器即pod内主容器启动之前要运行的容器,主要是做一些前置工作,初始化容器具有一下特征:
-
声明周期钩子函数
- k8s为容器提供了两种生命周期钩子:
- Poststart(破斯特 start):于容器创建完成之后立即运行的钩子程序
- perStop:容器终止之前立即运行的程序,是以同步的方式进行,因此其完成之前会阻塞 删除容器的调用
- 备注: 钩子程序的执行方式有 "Exec" 和 "HTTP" 两种。
- k8s为容器提供了两种生命周期钩子:
-
容器探测
- 容器探测分为存活性探测和就绪性探测,容器探测是kubelet对容器健康状态进行诊断,容器探测的方式主要以下三种;
- ExecAction(exec 阿克神):在容器内执行指定命令。如果命令退出时的返回码为0,则认为诊断成功。
- TCPSocketAction(tcp socket 阿克神):对容器的ip地址上的指定端口执行tcp检查。如果端口打开,则诊断被认为时成功的
- HTTPGetAction(http get 阿克神): 对容器指定URL发起HTTP Get请求。响应码为2xx或者3xx为成功,否者失败
- 容器探测分为存活性探测和就绪性探测,容器探测是kubelet对容器健康状态进行诊断,容器探测的方式主要以下三种;
-
-
LivenessProbe(来奈斯 pro 部): 存活性探测
- 告诉kubelet对pod执行探测之后是否对pod进行重启
- 无论pod探测结果如何,都会把pod地址加入到service的endpoint中
-
ReadinessProbe(Read 乃是 pro 部): 绪性探测
- 即使探针探测失败也不会重启pod
- 探测失败后不会把pod地址加入到service的endpoint中
1、pod的创建过程
2、运行初始化容器
3、运行主容器(钩子和探针)
4、pod的终止过程
两个不同的pod的两个不同服务比如nginx和mysql是通过coerDNS定义pod解析的域名通信的
示例
不同pod的两个容器是如何通信的
同命名空间使用pode名称通信,不同命名空间通过service互相通信
-
servicename serviceip 为pod配置一个service
-
通过coerDNS定义pod解析的域名
-
我们一般在公司中就是写service全称,这个域名他有一个标准的命名格式,首先是service名称,然后是name space的名称,然后是svc,然后是domain后缀,这个后缀比较固定
-
helloworld.local不合适那么使用cluster.local
domain后缀:一般在公司中就是写service全称,这个域名他有一个标准的命名格式,首先是service名称,然后是name space的名称,然后是svc,然后是domain后缀,这个后缀比较固定
比如:kubernetes.default.svc.helloworld.local
kubernetes 是service名称,可以使用kubectl get service -A 查看
default 是namespace名称,可以使用 kubectl get service -A 或 kubectl get pod -A 查看
svc 是固定项
helloworld.local 是domain后缀,就是在dns中定义的domain后缀,可以在dns的yaml文件中的 kubernetes 字段,或者,在pod容器的/etc/resolv.conf文件查看
# 检测域名,这个域名在pod中必须是可以ping通的(这个就是dns组件去解析的)
ping helloworld-tomcat-app2-service.helloworld.svc.helloworld.local
# nginx代理后端服务
upstream tomcat_webserver { # 这里就是我们的最新配置,此容器无法直接运行,因为他无法找到helloworld-tomcat-app1-service.helloworld.svc.helloworld.local:80 这种地址,他必须在k8s中启动为pod才能通过k8s的dns解析
server helloworld-tomcat-app1-service.helloworld.svc.helloworld.local:80;
server helloworld-tomcat-app2-service.helloworld.svc.helloworld.local:80;
}
iptables和ipvs的区别优势是什么
示例
IPtables与IPVS都是基于Netfilter实现的,但因为定位不同,二者有着本质的差别:
IPtables是为防火墙而设计的;
IPVS则专门用于高性能负载均衡,并使用更高效的数据结构(哈希表),允许几乎无限的规模扩张
IPtables优势灵活,功能强大,劣势是他的规则通过遍历匹配,时间成本高
ip vs优势工作在内核态,有更好的性能,调度算法丰富: 有r r(轮询调度)、l c(最小连接数)、d h(目标哈希)、ip(源哈希)
namespace资源隔离都隔离了哪些
示例
namespace资源隔离都隔离了哪些
U T S 主机名与域名
ip C 信号量、消息队列和共享内存
P I D 进程编号
Net work 网络设备、网络栈、端口等等
Mount 挂载点(文件系统)
User 用户和用户组
如何更改kube-porxy的网络模式,以及算法
示例
如何更改kube-porxy的网络模式,以及算法
在kube-proxy的config文件中,可以修改mode指定网络模式,添加IPVS 配置修改调度算法,然后重启kube-proxy,使用ipvsadm命令 -L n 选项,查看调度算法是否生效
二进制部署的在yaml文件中更改,kubeadm部署的更改configmap
# 查看当前调度算法(可以看到当前算法是rr)
root@k8s-master1:~# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.200.0.1:443 rr
-> 10.0.0.3:6443 Masq 1 0 0
TCP 192.200.0.2:53 rr
-> 172.200.169.193:53 Masq 1 0 0
TCP 192.200.0.2:9153 rr
-> 172.200.169.193:9153 Masq 1 0 0
UDP 192.200.0.2:53 rr
-> 172.200.169.193:53 Masq 1 0 0
# service文件中指定了一个yaml的配置文件
root@k8s-master1:~# cat /etc/systemd/system/kube-proxy.service
...
--config=/var/lib/kube-proxy/kube-proxy-config.yaml
...
# 修改kube-proxy-config.yaml文件,在此文件中使用mode指定模式是什么,然后添加ipvs的配置,然后添加scheduler的值修改为算法
root@k8s-master1:~# vi /var/lib/kube-proxy/kube-proxy-config.yaml
...
mode: "ipvs" # 可以看到当前模式为ipvs
ipvs: # 添加ipvs的配置,然后添加scheduler的值修改为sh算法,这个算法使用什么就修改为什么
scheduler: sh
# 重启kube-proxy服务
root@k8s-master1:~# systemctl restart kube-proxy
# 在查看,可以看到当前调度算法为sh(但是这个配置仅对当前服务器生效,对于别的主机还是使用的是默认的rr轮询,所以说如果要修改,那么所有服务器都要修改为相同的算法)
root@k8s-master1:~# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.200.0.1:443 sh
-> 10.0.0.3:6443 Masq 1 0 0
TCP 192.200.0.2:53 sh
-> 172.200.169.193:53 Masq 1 0 0
TCP 192.200.0.2:9153 sh
-> 172.200.169.193:9153 Masq 1 0 0
UDP 192.200.0.2:53 sh
-> 172.200.169.193:53 Masq 1 0 0
使用nodeport访问程序是什么流程
示例
使用nodeport访问程序是什么流程
请求进到安装了kube-proxy的任意节点的nodeport端口,然后通过IPVS 规则转发到target Port端口,也就是service的端口,然后在把请求转发到后端的pode上,
单纯启动一个pod需要经过controller-manager吗
示例
单纯启动一个pod需要经过controller-manager吗
不需要,因为创建单个pode不经过控制器,不受控制器管理,自然就不经过controller-manager了
awk取第二行的第二列
示例
awk取第二行的第二列
首先 awk 是取列的,通过-F选项指定分隔符,通过print指定打印第几列,取出列后,接着通过管道符使用sed 指定2 p 取行
# 使用awk 使用大写的F选项,用于指定分隔符,使用花括号打印$2就表示打印第二行,对行的处理我们使用sed,使用-n不自动打印,使用2p打印第二行到屏幕
awk -F '{print $2}' | sed -n "2p"
[root@localhost ~]# awk -F" " '{print $2}' ./a.txt | sed -n '2p'
b
使用sed把大写的A替换成小写的a
示例
怎么使用sed把大写的A替换成小写的a
我们使用sed 的查找替换的方式,指定s使用查找替换,查找大写的A 然后替换成小写的a,然后指定修饰符 g p 全文替换,并打印出来,或者使用- i 直接编辑文本
查看java的所有进程
示例
怎么查看java的所有进程
使用p s 通过-e选项表示显示所有进程,-f选项把进程的所有信息都显示出来,然后使用grep 过滤出java的进程
Maven 的编译命令
示例
1.进入到包含有“pom.xml”的路径,执行(这个clean表示清空当前环境,他会把历史编译的环境清空一下,然后给你重新编译):
mvn clean install package
2.有的时候受到测试的干扰,导致无法正在进行编译,这时候可以选择跳过测试:
mvn clean install package -Dmaven.test.skip=true
" -Dmaven.test.skip=true":-D跳过测试,并且不编译测试下的源代码,我们一般都是跳过测试;
"-DskipTests":不执行测试,但是会进行测试代码的编译;
3.如果需要编译的代码异常庞大,需要考虑对编译环境做一些处理(开多线程),提成编译效率:
启动多线程编译(使用-T,4表示开启4个线程):mvn -T 4 clean install package -Dmaven.test.skip=true
分配编译的 CPU 个数(使用-T,2c表示使用两个cpu):mvn -T 2C clean install package -Dmaven.test.skip=true
启用多线程编译(最常用的编译命令,不用添加多线程):mvn clean install package -Dmaven.test.skip=true -Dmaven.compile.fork=true
4.所有的 Maven 都是建立在 JVM 上的,所以进行编译的时候还需要考虑 JVM 参数优化(比如内存较小,可能会编译失败):
如果是 windows 找到“maven/bin/mvn.cmd”,如果 linux 找到“maven/bin/mvn”,配置参数是:“MAVEN_OPTS”
打开属性配置文件:vim /etc/profile
追加一个配置项(通常情况下我们需要导入一个环境变量,-Xmx6g -Xms6g表示最大内存和最小内存,在公司中这种编译服务器一般都是24G或者32G,甚至64G,但是一般32G的比较多):export MAVEN_OPTS="-Xmx6g -Xms6g"
使配置立即生效:source /etc/profile
# 编译,这个可能需要很长时间(在当前目录下执行编译,-Dmaven.test.skip=true表示跳过测试)
root@mimabaohu:/usr/local/src/dubbo-admin# mvn clean package -Dmaven.test.skip=true
prometheus监控node
示例
-
各node节点安装node_exporter(node 爱x破儿德尔),用于收集各k8s node节点上的监控指标数据,默认监听端口为9100
-
(他监控node节点是通过node_exporter这个组件去监控的,这个可以理解为就是他的一个anget,这个node_exporter只是适用于监控node,或者master,etcd节点上的宿主机的资源情况,他监控不了容器的,监控容器需要安装别的组件)
# 这个可执行程序可以直接启动,但是需要在当前目录下启动(他都是通过参数的方式提供配置的,比如要修改他的监听端口 ./node_exporter --web.listen-address=":9900",他默认监听的端口是9100)
root@k8s-node1:/apps/node_exporter# ./node_exporter
# 另开一个终端查看端口,他启动之后会监听本地的9100端口(可以看到他已经监听了9100端口,这个端口可以直接访问的)
root@k8s-node1:~# ss -tnl
LISTEN 0 4096 *:9100 *:*
prometheus监控容器
示例
- cadvisor(啃得歪惹儿)由谷歌开源,cadvisor不仅可以搜集一台机器上所有运行的容器信息,还提供基础查询界面和http接口,方便其他组件如Prometheus进行数据抓取,cAdvisor可以对节点机器上的资源及容器进行实时监控和性能数据采集,包括容器CPU使用情况、容器内存使用情况、容器网络吞吐量及容器文件系统使用情况。
# 使用二进制方式启动服务
# 切换目录
[root@k8s-node02 ~]# cd /apps
# 下载cadvisor二进制包
[root@k8s-node02 apps]# wget https://github.com/google/cadvisor/releases/download/v0.39.3/cadvisor
# 添加可执行权限
[root@k8s-node02 apps]# chmod +x cadvisor
# 测试执行,查看帮助(这个包是编译好的,可以直接运行)
[root@k8s-node02 apps]# ./cadvisor --help
# 直接运行这个二进制文件,它就可以直接跑起来
[root@k8s-node02 apps]# ./cadvisor
# 打开另一个终端验证一下(可以看到他默认监听的端口是8080)
[root@k8s-node02 ~]# ss -tnlp | grep cadvisor
LISTEN 0 16384 [::]:8080 [::]:* users:(("cadvisor",pid=51706,fd=7))
# 起来之后我们就可以访问一下(它会收集很多当前宿主机容器的数据,他也可以收集一些宿主机的数据)
http://192.168.2.155:8080/containers/
## Docker Containers (# 点击这个)
# 我们访问metrics(这是一个API接口,可以提供很多监控指标)
http://192.168.2.155:8080/metrics
prometheus告警组件
示例
- alertmanager(阿勒 买内机儿)告警组件
# 配置alertmanager如何把通知发送出去
[root@k8s-master02 alertmanager]# vi alertmanager.yml
global:
resolve_timeout: 5m # 超时时间
smtp_smarthost: 'smtp.qq.com:465'
smtp_from: '2973707860@qq.com'
smtp_auth_username: '2973707860@qq.com'
smtp_auth_password: 'udwthyyxtstcdhcj'
smtp_hello: '@qq.com'
smtp_require_tls: false
route:(儒特) # route用来设置报警的分发策略(路由)
group_by: ['alertname'] # 采用哪个标签来作为分组依据(比如对属于同一个分组的仅发送一次告警)
group_wait: 3s # 组告警等待时间。也就是告警产生后等待10s,如果有同组告警一起发出(这个时间不要等待太长)
group_interval: 3s # 两组告警的间隔时间(这个时间也不要太长)
repeat_interval: 2m # 重复告警的间隔时间,减少相同邮件的发送频率(同一个告警重发发送间隔时间)
receiver: 'web.hook' # 设置接收人(接受人在receivers中定义)
receivers: (如谁贝尔) # 可以定义多个姐接收人
- name: 'web.hook' # 这个就是定义具体接收人
#webhook_configs: # 如果是钉钉需要往这个url发送一个调用,钉钉是需要写webhook才能够把信息发送出去
#- url: 'http://127.0.0.1:5001/'
email_configs: # 使用email方式
- to: '2973707860@qq.com' # 定义收件箱地址(这里发送邮箱和接收邮箱配置一致,表示我自己发给了我自己)
inhibit_rules: # 抑制的规则(保持默认即可)
- source_match: # 源匹配级别,当匹配成功发出通知,但是其他的通知将被抑制,也就是尽量减少我们发送通知的频率
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
# 启动alertmanager
[root@k8s-master02 alertmanager]# systemctl restart alertmanager
# 验证端口(可以看到9093端口已经被占用了)
[root@k8s-master02 alertmanager]# ss -tnlp | grep 9093
LISTEN 0 16384 [::]:9093 [::]:* users:(("alertmanager",pid=41640,fd=8))
运行pod的时候有很多节点牵扯到pod一个亲和和反亲和服务启动如何保证pod启动在指定的节点上
yaml文件中service的一些port--targetport-nodepod都是什么意思
1. 平时写dockerfile吗,简单说一下dockerfile
2. copy和add这两个dockerfile命令的区别
示例
相同点是都是拷贝到容器,不同点add会自动解压点gz压缩的包,copy不会
3. docker run参数
示例
docker run参数 比如-v -p -i 分别代表什么意思
--name 指定容器名称
-v 指定挂载卷
-p 指定暴露端口
-d 到后台运行
-i t 创建交互接口
--rm 容器关闭时自动删除容器
-h 容器启动时设置容器主机名
4. 容器起来之后,一直处于自动重启的状态,说一下排查思路
容器运行必须有pid为1的进程,频繁自动重启要检查一下程序本身,使用docker inspect命令查看是否 o o m被kill掉了
接着通过docker logs命令查看程序启动是否报错
5. 查看容器状态的命令,说两个
示例
使用docker ps -a 命令查看容器的状态
使用docker inspec命令查看容器的详细信息
使用docker logs 命令查看容器的日志
6. 工作中用到的docker版本
19.03版本,由systemcd进程管理containerd进程,containerd进程管理containerd-shim进程
20以后版本,由systemd进程直接管理containerd-shim进程
7. 说一下k8s组件
8. 说一下pod创建过程
9. 运行pod的时候有很多节点,牵扯到pod一个亲和和反亲和,服务启动如何保证pod启动在指定的节点上
10. k8s集群环境有多少节点
11. yaml文件中service的一些port , targetPort ,nodepod都是什么意思
示例
示例
root@kubeadm-master1:/opt/yaml/case2# vim 3-svc_NodePort apiVersion: v1 kind: Service metadata: name: ng-deploy-80-service spec: ports: - name: http port: 81 # service端口 targetPort: 80 # 目标pod服务所监听的端口 nodePort: 30012 # 宿主机映射端口 protocol: TCP type: NodePort # 这个service使用NodePort selector: # 选择器匹配pod标签 app: ng-deploy-80 ```12. service和pod之间的关系
示例
service和pod之间的关系
service可以理解为pode的负载均衡器,service通过selector匹配pode的标签,从而发现pode,然后将请求通过一定算法转发到这些pode上
14. 平时中说用的挂载所用的挂载使用那个(就是让说configmap)
示例
15. 公司中用helm,chart吗
16. 一个服务是如何起到k8s中的
示例
一个服务是如何起到k8s中的
首先我们需要了解要部署的服务,比如架构,配置,端口号,启动命令,接着我们需要这个服务的镜像,接着要确定合适的部署方式,比如服务是否有状态,有状态需要持久化数据,是否配置分离,部署yaml文件来源,如何部署,单实例使用Deployment,集群使用Helm,最后怎么访问,内部访问定义一个本地service,外部访问需要使用nodeport暴露端口
17. 起的pod现在发现有几十个都处于被驱逐的状态,这个会是什么情况导致的
示例
起的pode现在发现有几十个都处于被驱逐的状态,这个会是什么情况导致的
资源限额,资源不足时会被驱逐
节点下线,节点上的pode会被驱逐
手动删除
18. 批量删除指定状态的pode
示例
批量删除指定状态的pode
通过get pod 列出指定命名空间下的pode,然后使用grep 过滤Evicted 被驱逐状态的pode,然后使用awk 取第一列pode名称,然后使用xargs 命令传递给kubectl命令 delete选项,批量删除pode
19. 简单说一下pod状态
20. redis备份
示例
22. 查询一个tast表中,每一个tast列,中包含字符tast所有的条目
使用select 命令查询tast列,然后from 到 tast表进行查询,然后使用where使用like 匹配所有包含tast字符的条目
23. nginx反向代理和正向代理的区别
示例
nginx反向代理和正向代理的区别
正向代理:客户端向服务器发送请求,服务器将数据转交给客户端,客户端需要设置正向代理。
反向代理:客户端对代理无感知,服务器将请求发送到反向代理服务器,由服务器选择目标服务器获取数据后返回。
24. nginx中master进程和work进程说一下他俩的区别
示例
nginx中master进程和work进程说一下他俩的区别
master进程只有一个,负责监听端⼝,接受来⾃web server的请求。
worker进程一般会有多个,每个进程中会嵌⼊一个php解析器,进⾏php代码的处理。
25. nginx平滑升级
26. kafka和ZooKeeper
27. shell如何批量修改文件中的通用字符串,说一下有几种方式
shell如何批量修改文件中的通用字符串,说一下有几种方式
第一种,将文件路径赋值给变量,可以是多个文件,然后使用for循环这个变量,取出文件路径,然后对这些文件使用sed 进行搜索替换,-i选项直接修改文件本身
第二种,可以使用while read 读取文件中的每一行进行循环,然后在使用sed进行搜索替换
28. 使用什么linux服务器,内核是多少
使用什么linux服务器,内核是多少
使用的ubuntu 18点04 版本,内核是5点4点0
29. linux免密登录
linux免密登录
使用s s h-keygen命令生成的,私钥和公钥文件在用户目录下的点s s h下,我们把公钥文件发给客户端进行免密登录
31. su 和 sudo的区别
su 和 sudo的区别
su命令,用来切换用户
sudo命令,使用超级用户来执行命令
32. 开机自动挂载磁盘
开机自动挂载磁盘
在etc下的f s tab中编辑,将文件系统名称以及挂载路径写进配置文件
33. 如何查询进程的启动时间
如何查询进程的启动时间
使用ps 命令,使用-p选项指定进程id,然后使用-o选项指定lstart表示进程什么时候启动的,或者etime表示进程启动时长
1.什么是redis
示例
什么是redis
是一个高性能的 key-value 数据库,数据保存在内存中
2.redis的数据类型
示例
redis的数据类型
redis 支持 string(字符串),hash(哈希),list(列表),set(集合),sorted set(有序集合)
3.使用redis有哪些好处
示例
使用redis有哪些好处
速度快,因为数据存在内存中
支持数据类型丰富
支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
4.redis相比Memcached有哪些区别和优势
示例
redis相比Memcached有哪些区别和优势
memcached除了字符串以外的数据类型都不支持,redis 支持更多的数据类型
redis 写是单线程,而memcache是多线程,所以单机情况下没有memcache并发高
redis支持数据的备份
memcache单个key value最大只支持1MB,而redis单个key的值最大支持512MB
5.redis的持久化机制是什么各自的优缺点
示例
redis的持久化机制是什么各自的优缺点
redis提供两种持久化机制 R D B 和 A O F
R D B将数据从内存dump到磁盘,保存为r d b文件,优点是数据集大时,比a o f恢复效率高,缺点是上一次备份到服务器宕机这段时间的数据会丢失
A O F将命令行指令保存到磁盘中,保存为 a o f 文件.优点是上一次备份到服务器宕机这段时间的数据会通过命令行指令的方式保存,数据安全性高,缺点是数据集大时,比R D B恢复效率低,因为它要一条一条执行指令
6.redis主从复制过程
示例
redis主从复制过程
从服务器连接主服务器,发送同步指令,主服务器接收后开始生成R D B 快照文件,并使用缓冲区记录新执行的写指令,完成后主服务器将R D B 和 缓冲区记录的写指令发送给从服务器,最后从服务器先载入新R D B快照文件, 在执行缓冲区写指令,完成后发送自己slave_repl_offset位置,只同步新增加的数据,不再全量同步。
7.redis集群哨兵
示例
redis集群哨兵
哨兵机制可以解决master和slave角色的切换问题,哨兵需要服务器至少一主两从,分别在这三个服务器上再起一个哨兵的进程,或者在单独服务器上安装,让哨兵去监控我们redis的master状态
8.rediscluster
示例
redis Cluster
redis Cluster既实现高可用,又实现性能提升,生产环境推荐至少三主三从,节点之间通过ping探测对方是否存活,它提出了一个槽的概念,一共有16284个槽位分别分配给master服务器,在槽位上写数据,这样共享服务器的内存,带宽,磁盘,实现横向扩容,但是客户端需要知道所有的服务器地址,从而计算槽位位置
单词发音
第6章 K8s基础篇-基本概念
示例
为什么要用K8s,
第一,首先裸容器的问题,宿主机宕机容器无法自动恢复,
第二,程序级健康检查依旧不到位,
第三,程序的扩容、部署、回滚和更新依旧不够灵活,
第四,端口问题并未得到解决,
所以容器编排应运而生,
它可以轻松管理成千上万的业务容器,
有全自动容灾机制,
有全自动扩缩容、回滚,
有原生支持服务发现和负载均衡,
也有更加灵活方便的健康检查
k8s架构解析,
K8S是一个主从的架构,主节点我们在生产环境推荐3个起步,e t c d 集群也是推荐3个起步,这是最基础的,因为我们数据是不能丢的,不能部署是2个或者4个,这种偶数部署,因为会有脑裂问题,e t c d和master是可以不在同一个服务器的,这个e t c d在生产环境中一定要用独立的磁盘,并且一定要是ssd的磁盘,从节点是真正部署我们Pode的节点,这个从节点理论上可以无限的扩容,这个多主节点和从节点通信,都是通过load balancer(LB负载)进行通信的,e t c d只有主节点的apiserver和他通信,还有就是kubectl客户端工具,可以独立部署,可以不和集群在一块,只需要和LB或者某个master节点网络是通的就可以操作集群
控制节点组件剖析,控制节点组件有APIServer, Scheduler, Controller Manager
APIServer是整个集群的控制中枢,提供集群中各个模块之间的数据交换,并将集群状态和信息存储在e t c d集群中。同时他也是集群管理,资源配额,提供完备的集群安全机制的入口,为集群各类资源对象提供增删改查以及watch的REST API接口
Scheduler是集群Pode的调度中心,主要是通过调度算法将Pode分配到最佳的Node节点,他通过APIServer监听所有Pode的状态,一旦发现新的未被调度到任何Node节点的Pode(PodeSpec.NodeName为空),就会根据一系列策略,选择最佳的节点进行调度
Controller Manager是集群状态管理器,以保证Pode或其他资源达到期望值。当集群中某个Pode的副本数或其他资源因故障和错误导致无法正常运行,没有达到设定的值时,Controller Manager可以尝试自动修复并使其达到期望状态
E t c d是由CoreOS开发,用于可靠的存储集群的配置数据,是一种持久性,轻量型,分布式的键-值(key-value)数据存储组件,作为Kubernetes集群的持久化存储系统
我们的Scheduler和Controller Manager是有状态组件,
APIServer是无状态组件,因为APIServer的数据是保存在etcd中的,LB调用哪个节点的APIServer,就有哪个节点APIServer进行处理,但是Scheduler和Controller Manager是没有请求调用他们的,三个节点Scheduler和Controller Manager不可能都工作,所以他们是有一个选主的机制的,仅有一个节点工作,避免每个节点都执行,所以这两个组件是有状态的服务,状态信息保存在 leases 资源中
工作节点组件剖析,
工作节点组件有kubelet,和 kube-Proxy,和 Runtime,和 CoreDNS,和 Calico
kubelet:负责与Master通信协作,管理该节点上的Pode,对容器进行健康检查及监控,同时负责上报节点和节点上面Pode的状态
kube-Proxy:负责各Pode之间的通信和负载均衡,将指定的流量分发到后端正确的机器上
Runtime:负责容器的管理
CoreDNS:用于kubernetes集群内部Service的解析,可以让Pode把Service名称解析成Service的IP,然后通过Servier的IP地址进行连接到对应的应用上
Calico:符合CNI标准的一个网络插件,它负责给每个Pode分配一个不会重复的IP,并且把每个节点当做一个 “路由器” ,这样一个节点的Pode就可以通过IP地址访问到其他节点的Pode
什么是Pode,
Pode可简单地理解为是一组,一个或多个容器构成,是k8s所管理的最小单元,每个Pode还包含一个Pause容器他是Pode的父容器,它主要负责僵尸进程的回收和管理,通过Pause容器可以使同一个Pode里面不同的多个容器共享存储,网络,PID,IPC等,容器之间可以使用本地ip 加 端口号互相访问
为什么要引入Pode
强依赖的服务需要部署在一起,比如nginx和php
多个服务需要协同工作,比如某些服务需要初始化一些数据,或者是运行前需要拉一些东西才能去部署
兼容其他CRI标准的运行时
定义一个Pode
第一种方式通过kubectl命令加 run选项,指定要创建的Pode的名称,然后指定要使用的镜像这种方式创建一个Pode
第二种方式通过文件的形式去创建,这是一种声明式的方式,就是我们把想要的东西都写在一个文件里面,通过kind指定要创建的资源类型是Pode,然后在spec的container中可以指定多个容器,比如name容器的名字是什么,image容器的镜像是什么
修改容器的启动命令
在spec下的containers中指定command或args,可以替换容器内的启动命令,command对应dokerfile的ENTRYPOINT命令,args对应dokerfile的CMD命令
Pode状态及问题排查方法
Pending(挂起)
Running(运行中)
Succeeded(成功,容器执行成功并终止,并且不会再次重启)
Failed(失败,容器以失败,非零状态的方式终止)
Unknown(未知)
ImagePullBackOff 和 ErrImagePull (镜像下载失败)
CrashLoopBackOff (容器启动失败)
OOMKilled (容器内存溢出)
Terminating (Pode 正在被删除)
ContainerCreating (Pode 正在创建,比如正在下载镜像)
Pode镜像拉取策略
在container容器内的imagePullPolicy下定义
Always,总是拉取镜像
Never,不管镜像是否存在都不会拉取
IfNotPresent,镜像不存在时拉取镜像,本地存在此镜像就不在拉取了
Pode重启策略
在spec内的restartPolicy下定义
Always,容器失效时,自动重启该容器
OnFailure,容器以不为 零 的状态码终止,自动重启该容器
Never,无论何种状态,都不会重启
探针
startupProbe(启动探针,Pode第一次启动执行,执行成功前会禁用其他探测)
livenessProbe(存活探针,探测容器是否在运行,如果探测失败,kubelet 会“杀死”容器并根据重启策略进行相应的处理)
readinessProbe(就绪探针,如果探测失败,就把服务从负载均衡上摘除,流量不能转发到探测失败的容器上)
探针的四种探测方式
Exec,在容器内执行一个指定的命令,如果命令返回值为 0,则认为容器健康
TCPSocket,通过 TCP 连接检查容器指定的端口,如果端口开放,则认为容器健康
HTTPGet,对指定的 URL 进行 Get 请求,如果状态码在 200~400 之间,则认为容器健康
gRPC,1.24添加的新功能
Pode启动过程
提交创建Pode的指令的时候,apiserver收到这个指令,这个Pode就会处于 Pending状态,他要去选择某一个节点去部署,当这个节点确定了之后,这个Pode状态会变成 ContainerCreating状态 可能在拉取镜像,镜像拉起来之后 Pode的状态就变成 Running状态,如果有 initContainer初始容器先执行 initContainer初始容器里面的操作,然后才会去启动 Container主容器,然后如果我们三个探针都配置了,他先执行 StartupProbe启动探针,探测成功后才会去执行 LivenessProbe存活探针 和 ReadinessProbe就绪探针,这两种探针也是成功的状态,他会在 Endpoint端点 里面添加 Pode的 IP地址 , 这个就是我们Pode整个启动的过程
Pode平滑退出
提交了一个删除Pode 命令, apiserver 收到删除Pode的指令, 会把Pode状态标记为 Dead(死的),并给一个30秒的宽限期,然后Pode他会变成一个Terminating状态,同时如果说配置了PreStop钩子函数,也会同时执行这个钩子,同时如果配置了 service , 这个 Endpoints端点 会直接性的把这个Pode 的 IP 地址删除,也就是说这个 Terminating状态 , PreStop , Endpoints,他们三个是同时进行的,虽然说把这个Pode 的 IP 从 Endpoints端点 删除了,但是有一些已经进来的流量,还是在处理的过程中,假如说配置了一个 PreStop ,但是这个 PreStop 没有在30秒之内结束掉,他会在给你加一个2秒的宽限期,也就是说他会等你32秒,在32秒之后,他不管你程序有没有处理完成,他就会给你强制删除,Pode就会收到一个SIGKILL信号,这个时候kubelet就会把Pode给删除掉,这个就是Pode他整个退出的过程
钩子函数
postStart:容器创建之后执行,如果失败了会重启容器
preStop :容器终止之前执行,在其完成之前会阻塞删除容器的操作
钩子函数支持 Exec 和 TCPSocket 和 HTTPGet三种方式定义动作
Pause(泡死)
create (奎A特)
cmd
ENTRYPOINT entrypoint(按催 泡音特)
command (康 迈特)
args (啊尔 可死)
load balancer (楼的 掰了嗯 思儿)
watch (喔次)
REST API(瑞挨 斯特)
leases(雷 瑟斯)
Pending (判定)
Running (run宁)
Succeeded (谁可谁 待的)
Failed (非奥的)
Unknown (按 no)
ImagePullBackOff (音没记 噗哦 百克 奥福)
ErrImagePull (爱尔 音没记 噗哦)
CrashLoopBackOff (夸啊洗 路普 百克 奥福)
OOMKilled (oom Q特)
Terminating (特么 内定)
SysctlForbidden (谁死头 佛 拜瞪)
Completed (肯 普A 呆得)
ContainerCreating (啃腿哪儿 奎A定)
imagePullPolicy (音妹纸 噗 泼勒谁一)
restartPolicy (瑞 思 得儿特 泼勒谁一)
Always (欧位死)
Never (南无儿)
IfNotPresent (if not 婆尔 什特)
latest (勒的 斯特)
OnFailure (昂 非类而)
startupProbe (思 得儿特 啊普 Pro)
livenessProbe (来 奈斯 Pro)
readinessProbe (瑞地 奈斯 Pro)
ExecAction (exec 哎可心)
TCPSocketAction (TCPSocke 哎可心)
HTTPGetAction (HTTPGet 哎可心)
Prestop (普洱 stop)
SIGTERM (谁死 特尔木)
postStart (珀斯特 思得儿特)
lifecycle (来福 塞抠)
initialDelaySeconds (音内秀哦 地累 撒肯此)
timeoutSeconds (timeout 撒肯此)
periodSeconds (皮锐艾德 撒肯此)
successThreshold (success 思啊羞德)
failureThreshold (费哦耶儿 思啊羞德)
第7章 K8s基础篇-资源调度
示例
什么是无状态调度Deployment
无状态的应用,就是这个应用可以随时重启,然后重启完之后,它产生的一些临时文件,是不需要保存的,或者是不需要保证我pod的主机名是什么,不需要保证IP地址是什么
Deployment一般用于部署公司的无状态服务,也就是需要支持弹性扩缩容的应用
Deployment部署过程
Deployment首先去创建一个RS,由RS去创建pode
创建Deployment
通过定义kind资源类型是Deployment,然后在spec下定义Deployment资源,比如replicas他有几个副本,selector他所管理的pode的标签,然后template就是定义pode资源
Deployment滚动更新
通过kubectl命令,set选项,修改image,然后后面跟上资源类型和要更新的镜像名称,通过--record等于true参数可以记录本次更新
更新过程可以通过rollout 参数的status 查看,可以看到更新过程为新旧交替更新,首先新建一个 Pode,当 Pode 状态为 Running 时,删除一个旧的 Pode,同时再创建一个新的 Pode,主要是Deployment在更新时创建了一个新的RS ,旧的RS 默认会被保存
Deployment回滚
通过rollout 参数的undo 选项可以回滚到上一个版本,通过添加--to-revision选项可以回滚到指定版本
Deployment扩容和缩容
可以使用e d i t直接修改 replicas 副本数,实现扩缩容,或者使用scale 命令使用--replicas修改副本数量,实现扩缩容
Deployment暂停和恢复
rollout选项的pause参数可以暂停 Deployment 更新,通过rollout选项的resume参数恢复更新,这样可以避免修改一次更新一次,可以实现多次修改一次更新
Deployment历史版本清理策略
默认情况下,Deployment 保留 10 个旧的 ReplicaSet,其余的将在后台进行垃圾回收,可以在Deployment的spec下的revision History Limit 设置保留 ReplicaSet 的个数。当设置为 0 时,不保留历史记录
Deployment更新策略
Recreate,表示重建,先删掉旧的Pode再创建新的Pode
RollingUpdate,表示滚动更新,默认策略,可以指定 回滚更新时最大不可用的Pode数量 和 可以超过期望值的最大Pode数 两个参数来控制滚动更新过程
什么是有状态调度StatefulSet
有状态服务,表示有以下其中任何一个需求的,比如需要稳定的独一无二的网络标识符,需要持久化数据,需要有序的,优雅的部署和扩展,需要有序的自动滚动更新,都可以使用StatefulSet去部署有状态的且需要有序启动的应用程序
StatefulSet部署过程
StatefulSet是没有RS副本集,直接在命名空间下创建一个StatefulSet实例,然后有序启动pode,任意一个pode启动失败,后续pode不会启动
什么是Headless Service
StatefulSet创建的Pode一般用于 无头服务 Headless Service 进行Pode之间的通信,和普通的Service的区别在于Headless Service没有ClusterIP,他使用的是Endpoint进行互相通信
创建一个StatefulSet
先创建一个 无头服务 保持clusterIP是None,然后创建StatefulSet, 指定kind资源类型是StatefulSet,然后在spec下定义 serviceName 就是指定 无头服务 的名称,然后replicas定义要创建的副本数,和selector他所管理的pode标签,最后template也就是pode的配置
StatefulSet创建和删除Pod的过程
按顺序从0到N开始创建Pode,删除Pode时,将按照N到0的反顺序终止,不管创建还是删除中间有失败的pode都会停止后续的操作
Headless Service通信原理
无头服务为我们每一个Pode提供了一个域名,这个域名可以被解析为IP地址,这样的话受 StatefulSet 管理的Pode就可以通过这个service可以去互相的访问
StatefulSet扩容和缩容
通过更新 replicas 字段扩容 和 缩容 StatefulSet,也可以使用scale 或e d i t 来扩容或缩容
StatefulSet更新策略
On Delete 策略,删除一个pode,更新一个pode,不删除他不更新
RollingUpdate 策略,滚动更新会自动更新一个 StatefulSet 中所有的 Pode,采用与序号相反的顺序进行滚动更新。
StatefulSet灰度发布
StatefulSet 独有的功能叫 "分段更新" 可以更新一部分的pode,实现一个简单的灰度发布,通过RollingUpdate 策略 的 partition 这个参数指定pode序列号,大于或者等于这个序列号的都会被更新
什么是守护进程DaemonSet
守护进程集DaemonSet和守护进程类似,他在符合匹配条件的节点上均部署一个Pode
创建一个DaemonSet
定义kind资源类型是DaemonSet,然后在spec下定义selector他所管理的pode的标签,然后在template下,也就是pode模板中的spec下定义nodeSelector参数,指定要匹配的node标签,他会部署pode到有这些标签的node上,如果nodeSelector参数没有定义,他会部署到集群中所有符合条件的节点上
DaemonSet更新策略
有 OnDelete 和 RollingUpdate 两种更新策略,为了安全考虑可以使用 OnDelete 作为更新的方式,因为 DaemonSet影响范围比较广,手动的删除某一个节点上的pod,去看一下他能不能起来,如果说不能起来,我们就不要去更新其他的节点了
什么是HPA
水平 Pode 自动缩放器,根据我们部署的metrics-server组件观察到的cpu和内存的使用率,通过调整pod数量,来扩容pode数量降低压力,和缩容pode数量节省资源
自动扩缩容HPA实践
使用autoscale选项,指定--cpu-percent指定cpu指标,然后--min表示缩容的最小副本数,--max表示最大的扩容副本数
ReplicaSet (瑞 普雷卡 Set)
Replication (瑞 普雷 腿逊)
StatefulSet (史蒂夫 Set)
replicas (瑞 普雷 卡死)
rollout (如 奥特)
record (瑞啊 根的)
status (斯戴特 思)
describe (的士 可瑞 博)
revision (瑞 微什)
undo (按 度)
scale (思 该奥)
pause (刨丝)
resume (瑞 搜木)
strategy (思 抓的及)
rollingUpdate (如 淋 Update)
maxUnavailable (max 啊那 为了波)
maxSurge (max 设计)
patch (派吃)
partition (胖儿 泰逊)
cascade (卡死 给特)
metrics (卖 雀克斯)
autoscale (澳头 死该哦)
--cpu-percent (普尔 森特)
第8章 K8s基础篇-服务发布入门
示例
在K8s上是如何发布服务的
pode重建那么pode的ip地址会改变,我们通过service资源,把请求代理的后端被标签匹配到的pode上,这样可以通过service名称访问到pode,无论你的pode进行更新也好,删除,或者是扩容也好pode的ip地址怎么改变,service都能自动的发现pode实例,将流量转发给后端的pode上
什么是Label和Selector
Label,是标签,可以对Pode和节点等资源进行 “分组” ,用于区分同样的资源不同的分组
Selector,是标签选择器,可以根据资源的标签查询出精确的对象信息
定义 Label
使用kubectl命令的label 选项对需要打标签的资源,比如node资源打上key/value格式的标签
Selector 选择器
在使用get查看资源的时候,使用--show-labels 查看指定资源目前已有的 所有Label,或者使用-l选项过滤标签
修改标签
需要添加上 --overwrite 参数进行修改value,把value覆盖,否则直接修改会报错,说这个key已经有一个value了
删除标签
创建标签的格式,后面添加一个 减号,删除标签
什么是Service
一种可以访问Pode的策略,一组Pode能够被Service通过标签选择器访问到,之后就可以使用Service进行通信
Service的基本使用
定义kind资源类型是Service ,然后在spec下定义selector他所管理的pode的标签,然后type定义service类型,如果不写type默认是ClusterIP类型,然后在ports下定义端口号,port表示service自己的端口号,targetPort表示容器的端口号,通过访问service的端口号可以访问到容器的端口号
Service的类型
ClusterIP:在集群内部使用,是默认值
NodePort:在所有安装了 Kube-Proxy 的节点上打开一个端口,可以通过 NodePort 从集群外部访问集群内的服务
LoadBalancer:使用云提供商的负载均衡器公开服务,成本较高
ExternalName:通过返回定义的域名,也就是访问此类型的service就访问了定义的域名
使用NodePort对外发布服务
将 Service 的 type 字段设置为 NodePort,将从--service-node-port-range 参数指定的范围中自动分配端口,默认为 30000-32767,也可以手动指定此范围内的端口号,创建该 Service后,集群每个节点都将暴露一个端口,通过某个宿主机的 IP地址加端口号即可访问到后端的应用
查看 Endpoints
创建service的时候自动的创建一个 同名的Endpoints,存储了同名称service所管理的pode的ip地址列表
使用Service代理K8s外部服务
创建service指定类型是ClusterIP,创建一个和service同名的Endpoint,除了subsets下的addresses定义的ip地址,其余都和service定义相同这样就可以被service所代理,这样当我们访问此service时可以被代理到Endpoint定义的ip地址上
什么是ingress
service都配置的NodePort,那么很多端口号管理起来特别麻烦,通过节点的地址访问到服务,如果节点挂了服务也就挂了,需要在节点前面添加代理服务器,但是不推荐这样做,因为有ingress可以提供负载均衡
使用ingress发布服务的流程
浏览器访问域名解析成ip地址,通过ip地址进入网关,通过网关到达ingress然后达到service最后到达pode
ingress组成
ingress有ingress Controller和资源ingress组成,ingress Controller可以理解为nginx,资源ingress可以理解为nginx.conf配置文件
使用域名发布K8s内部服务
定义kind类型是ingress,然后在spec下定义ingressClassName这是我们在安装ingress Controller时候定义的,用于将In gress配置通过ingressClass找到ingress Controller,相当于把nginx.conf文件,配置到nginx,然后定义rules就是路由规则,定义host就是域名是什么,然后http下的paths就是代理到后端哪个服务的哪个端口号和路径上去,完成流量的转发
Selector (斯莱克特儿)
overwrite (哦佛 歪特)
targetPort (塔儿 get port)
protocol (pro 特 考)
range (润纸)
subsets (傻不 set 思)
addresse (啊绝儿 思)
addresses (啊绝儿 色思)
ClusterIP
NodePort
LoadBalancer(楼的 掰了嗯 思儿)
ExternalName (埃克斯 特儿NO Name)
Endpoints (按的 破音特斯)
backend (百 啃嗯的)
subsets (扫不 什思)
addresses (啊 角儿死)
rules (如肉思)
Exact (埃克 热 科特)
Prefix (普A 非可视)
ImplementationSpecific
第9章 K8s基础篇-配置管理
示例
云原生要素-配置分离
把代码和配置拆分出来,不要放在一起
创建ConfigMap的几种形式
基于目录创建 ConfigMap,通过kubectl命令,create cm 自定义cm名称,通过--from-file指定目录创建configmap
基于文件创建configmap,,通过kubectl命令,create cm 自定义cm名称,通过--from-file指定文件创建configmap
引用变量创建configmap,,通过kubectl命令,create cm 自定义cm名称,通过--from-env-file指定文件,仅引用文件中的变量创建configmap,不在confugmap中添加文件名称
使用yaml文件创建configmap,指定kind类型是configmap,在data下创建数据
使用valueFrom定义环境变量
在容器内env下定义name变量的名称,然后变量值的来源使用valueFrom,我们从指定configmap中的一个key来获取值,然后赋值给name完成环境变量的定义
使用envFrom批量生成环境变量
在容器内定义和env同级,通过 envFrom可以直接把整个 configmap中的所有内容生成环境变量
以文件的形式挂载ConfigMap
通过定义volumes定义要挂载的configmap,可以在这里定义default Mode和i tmes来定义权限和名称,然后在容器内通过volumeMounts把configmap挂载到容器的某个路径下
Secret常用类型
创建Secret要指定类型
Opaque:通用型Secret,默认类型
dockerconfigjson:下载私有仓库镜像使用的Secret
tls:用于存储HTTPS域名证书文件的Secret
创建Secret的几种形式
通过文件创建Secret,通过kubectl命令,create secret指定secret类型,然后指定secret自定义名称,然后--from-file指定文件,创建secret
通过使用--from-literal直接以key/vlaue形式创建Secret
从yaml文件创建 Secret,指定kind类型是Secret,在data下创建数据
使用Secret拉取私有仓库镜像
创建好docker-registry类型的Secret,然后在template下的spec定义imagePullSecrets就是要使用什么Secret来拉取镜像
Secret管理HTTPS证书
创建好tls类型的Secret,然后在Ingress的spec下定义tls指定secretName名称是什么
使用SubPath解决挂载覆盖
在volumeMounts下定义subPath指定挂载名称,意思就是告诉容器要以文件的形式挂载,只挂载这一个文件,不要覆盖整个目录,然后在mountPath定义文件的全路径
热更新
将修改的配置文件,重新创建一下资源,但是使用--dry-run等于client不真正执行,然后输出为yaml文件,通过管道符给replace -f 横- ,执行一遍来实现热更新
valueFrom (value From)
Ref (瑞 福)
envFrom (env From)
items (爱的 慕斯 )
Secret (谁 奎尔特)
Opaque (O 配克)
account (啊看奥特)
token (头 根)
basic (杯 塞可)
auth (奥 思)
generic (吉 奈瑞 可)
stringData (史俊 data)
registry (瑞 鸡屎 翠咦)
immutable (A 缪特 布偶)
subPath (纱布 派斯 )
第10章 K8s进阶篇-持久化存储入门
示例
Volumes
翻译过来就是卷的意思,这个卷是做一些文件存储,卷只是一个目录,Pode 中的容器可以访问它。要使用卷 Pode需要通过.spec下的volumes 字段指定为 Pode 提供的卷,以及使用spec下的containers的volumeMounts 字段为容器指定卷挂载的目录
emptyDir
emptyDir卷用于 Pode 中的不同 Container 共享数据
hostPath
把宿主机上的文件或者目录挂载到pode上
为什么要引入PV和PVC
这个volume可能有一些比较高级的功能他无法实现,比如只读挂载,存储只能被一个pode挂载,限制pode使用空间, PV是由Kubernetes管理员设置的存储把PV绑定到后端的存储上,PVC是对存储PV的请求
pv回收策略
Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在
Recycle:回收,会清理pv,并使pv可用于下一个新的PVC,只有NFS和HostPath支持该策略,本策略将来会被弃用
Delete:删除,删除PVC时会同时删除PV,动态卷默认为Delete,大多数存储支持此策略
pv访问策略
Read Write Once:可以被单节点以读写模式挂载
Read Only Many: 可以被多个节点以只读模式挂载
Read Write Many:可以被多个节点以读写模式挂载
Read Write Once Pod :只允许被单个Pod访问
文件存储、块存储、对象存储区别
文件存储:一些数据可能需要被多个节点使用
块存储:一些数据只能被一个节点使用
对象存储:由程序代码直接实现的一种存储方式,一般是符合S 3协议的云存储
PV的状态
Available:可用,没有被PVC绑定的空闲资源
Bound:已绑定,已经被PVC绑定
Released:已释放,PVC被删除,但是资源还未被重新使用
Failed:失败,自动回收失败
创建PV,并进行PVC挂载
定义kind资源类型是PV,然后在spec下定义storageClassName通过此名称被pvc挂载,定于capacity要申请多大的storage容量,定义accessModes访问模式,接下来就是配置存储,比如hostPath,定义pvc是不关心后端的存储是什么类型的,他只关心storageClassName是什么,accessModes的访问模式是什么,storage大小是什么,他只有那么多配置,然后在deploy中使用volume挂载pvc
PVC一直Pending的原因
PVC申请的空间大小,大于PV的大小
PVC的StorageClassName没有和PV的一致
PVC的accessModes和PV的不一致
挂载PVC的Pod一直处于Pending
PVC没有创建成功/PVC不存在
PVC和Pod不在同一个Namespace
Volumes(喔有木思)
emptyDir(爱木题议 dir)
medium (美的 爱慕)
hostPath (豪是特 怕思)
Container (啃腿哪儿 )
Cluster (克拉斯的儿)
Directory (德歪 特锐)
PV
StorageClass (思 道尔几 克拉斯)
Retain (瑞 腿音)
Recycle (瑞 塞口)
Delete
ReadWriteOnce (Read 歪特 碗此)
ReadOnlyMany(Read 欧里 埋尼)
ReadWriteMany (Read 歪特 埋尼)
ReadWriteOncePod(Read 歪特 碗此 pod)
capacity (克 拍死地)
accessModes (唉科塞斯 mode)
Available (啊 魏了 布)
Bound (班奥的)
Released (瑞 李斯特)
Failed (非 哦 的)
claim (克雷姆)
第11章 K8s进阶篇-高级调度计划任务、污点和容忍、Affinity
示例
job
计划任务,执行脚本
CronJob
周期性的计划任务,在生产环境中Cronjob用的多,执行CronJob,他会创建job,这个job在创建一个pod去执行指令
初始化容器InitContainer
主容器一般不应该包含多余的工具和root身份的权限,通过初始化容器有这些工具和权限做一些对主容器的初始化操作
临时容器
给pode里面注入一个临时容器,具有Debug工具
污点Taint
Taint在一类服务器上打上污点,让不能容忍这个污点的Pode不能部署在打了污点的服务器上
NoSchedule污点:禁止调度到该节点,已经在该节点上的Pod不受影响
NoExecute污点:禁止调度到该节点,如果不符合这个污点,会立马或一段时间后被驱逐
Prefer NoSchedule污点:尽量避免将Pode调度到指定的节点上,如果没有更合适的节点,可以部署到该节点
创建方式使用taint选项使用nodes参数对节点打上污点,指定污点的key和value,然后加上EFFECT就是污点的级别
容忍Toleration
Toleration是让Pode容忍节点上污点,可以让一些需要特殊配置的Pode能够部署在具有污点的节点上,Toleration和nodeSelector是有区别的,nodeSelector是强制性的将pode部署在指定的节点上,Toleration是根据条件匹配,如果没有碰到污点那么就用不到了
在pode中的spec下定义然后定义key就是节点标签的key,定义value就是节点标签的Value,定义operator操作,有Equal表示平等,就是key 和 value 和 effect都完全匹配,还有Exists表示存在,表示匹配这些配置的参数就行,没有配置的不在乎,定义tolerationSeconds容忍污点时间,时间到了在迁移
内置污点
not-ready:节点未准备好
unreachable:访问不到节点
节点宕机秒级恢复应用
在controller-manager的service文件中的--node-monitor-grace-period定义节点不可用周期,这个节点在周期内一直不可用的,那么就会被标记为not-ready,那么pode飘逸时间应该是不可用周期时间秒加上tolerationSeconds定义的容忍污点时间,如果想快速恢复应用,就把这个时间设置的小点
Affinity亲和力
Node Affinity:节点亲和力/反亲和力
Pod Affinity:Pode亲和力
Pod Anti Affinity:Pode反亲和力
Affinity分类
硬亲和就是强制性的那就是硬亲和力,必须符合我这个条件
软亲和表示优先调度到满足条件的节点,如果不能满足在调度到其他节点
实现同一个应用分布在不同的宿主机
在spec下定义Affinity亲和力,使用pod Anti Affinity也就是Pode反亲和力,使用硬亲和力,然后定义labelSelector标签匹配规则,匹配key和values,使用operator的In绝对匹配,定义topologyKey拓扑域是kubernetes.io/hostname,这表示每一个node上的pode不可以存在定义的key和values相同的两个pode,这两个pode互斥,那么就会部署在别的宿主机,这样就实现了同一个应用多个副本分布在不同的宿主机
尽量将应用部署至高配置服务器
在spec下定义Affinity亲和力,使用node Affinity节点亲和力,使用软亲和,然后定义preference标签匹配规则,比如对ssd节点使用operator是in绝对匹配,对master节点使用operator是Not in不匹配就是反亲和力,然后他们的weight权重是100,然后在定义low ssd节点使用operator是l n绝对匹配,他的weight权重是10,这样我们的ssd节点如果挂了,他会部署在low ssd的节点上,而怎么也不会部署在master节点
拓扑域TopologyKey
通过匹配node节点上的key和value是否相同来判断是否是同一个域,key相同和value不同相当于是不同域,一个域可以比作相同主机,不同域相当于不同主机,这样我们可以把应用在多地区多机房部署
suspend (殊死 班的)
ttl Seconds After Finished(ttl 撒 肯 此)(奥特儿)(费内斯特)
backoffLimit (白客 奥夫 力米特)
completions (康普里 肾)
parallelism (派奥 劳恩什)
CronJob (宽嗯 job)
concurrencyPolicy (肯 可嗯 谁一 泼勒谁一 )
Allow (奥 老哦)
Forbid (佛 百特)
Replace (锐 普雷斯)
schedule (死该就)
successfulJobsHistoryLimit (谁克赛思 否 JobsHistoryLimit)
suspend (殊死 班的)
InitContainer (音内特 Container)
--feature-gates=EphemeralContainers (飞雀--给次--呃 反莫若Containers)
Taint (腿音 特)
Toleration (逃了 瑞什)
NoSchedule (no 死该就)
NoExecute (no 艾克斯 Q特)
PreferNoSchedule (泼菲尔 no 死该就)
operator (欧普 锐得儿)
Equal (已扣)
effect (爱 fai科特)
Exists (A克 热斯特)
tolerationSeconds (逃了 瑞什 撒 肯 此)
unreachable (昂 瑞 赤膊儿)
monitor (猫内特儿)
grace (格瑞斯)
period (Q 有的)
Affinity (爱妃内地)
PodAntiAffinity (pod A按提议 爱妃内地)
nodeSelectorTerms (nodeSelector 特尔慕 斯)
matchExpressions (马驰 A克斯 珀瑞森)
weight (威特)
preference (婆儿 佛尔池)
Exists (A克斯 热斯特)
DoesNotExist (德斯 not A克斯 热斯特)
TopologyKey (特跑乐吉 key)
--node-monitor-grace-period (node 毛内特儿 阁瑞斯 皮尔哎德)
第12章 Kubernetes进阶-高级调度准入控制
示例
K8s资源配额ResourceQuota
定义kind资源是ResourceQuota,有名称空间限制,针对定义的命名空间的做资源管理,在spec下的hard中定义,requests表示请求资源限制,也可以理解为创建资源时可以使用的资源,可以对cpu和memory进行限制,limits表示整个名称空间资源限制,可以对cpu和memory进行限制,还可以对pode 和 service 和 configmap 和 secret 等做资源数量限制
K8s资源限制LimitRange
ResourceQuota资源配额的限制,是根据resources参数来限制的,如果资源没有定义resources配置,这个ResourceQuota是没有用的,所以需要通过LimitRange定义一些默认值,如果资源没有定义resources参数,通过LimitRange定义的值来补充
定义kind资源是LimitRange在spec下的limits中定义,default是limit配置,defaultRequest是requests配置,然后定义max和max限制requests和limits的资源请求范围,然后定义type表示配置对象,比如我们对Container进行配置,也可以对pvc进行配置
K8s服务质量QoS
Guaranteed:最高服务质量,资源占用量明确,requests的cpu和memory和limits的cpu和memory配置的一致
Burstable: 服务质量低于Guaranteed,机器资源充足时,尽可能的使用更多的资源,limits字段的cpu和memory大于requests的cpu和memory的配置
BestEffort:服务质量低于Guaranteed和Guaranteed,该类型pode不配置资源配额参数
ResourceQuota (瑞 烧死 Q友哒)
hard (孩 的)
storage (思 道尔几)
requests (瑞 库外斯特)
LimitRange (limit 瑞记)
accessModes (艾克射死 Mode)
Guaranteed (改瑞 踢的)
Burstable (啵是 table)
BestEffort (百思 艾菲尔)
第13章 K8s进阶篇-细粒度权限控制
示例
什么是RBAC
RBAC分了4个顶级资源ClusterRole,Role,ClusterRoleBinding,RoleBinding
ClusterRole: 允许对整个集群做你想做的
Role: 只允许对该Namespace下的资源做你想做的
ClusterRoleBinding: 可以把ClusterRole配置的权限,授权给指定的“用户”,让他可以对整个集群做他想做的
RoleBinding: 可以把Role 和 ClusterRole配置的权限,授权给指定的“用户”,,让他可以对该Namespace做他想做的
RBAC配置解析
角色的定义的区别就是kind定义的资源是ClusterRole还是Role,其中ClusterRole没有名称空间限制, 然后在rules下定义apiGroups对哪些资源进行限制,他这个资源是属于哪个组的,也可以留空不写, 然后resources对这个组下的哪些资源进行授权,比如 pod,deployment ,service资源等,然后verbs可执行的操作,比如get查看,create创建等
绑定的定义的区别就是kind定义的资源是RoleBinding还是ClusterRoleBinding,其中ClusterRoleBinding没有名称空间限制,然后定义subjects把权限绑定哪个用户身上,kind定义资源的,比如user资源,name表示资源内的哪个用户,然后roleRef定义绑定什么权限,比如kind定义资源可以是 Role 或 ClusterRole资源, name表示要绑定的 Role 或 ClusterRole 这些角色的名称,这样通过subjects和roleRef就完成了用户和角色的绑定
默认 Roles 和 Role Bindings
cluster-admin: 管理员权限的ClusterRole,他的权限是最大的
admin: 比cluster-admin权限稍微要低调,多个管理员可以使用此权限
e d i t: 对集群有一个编辑的权限
view: 对集群有一个查看的权限
聚合ClusterRole
定义aggregationRule聚合规则,clusterRoleSelectors匹配聚合规则的标签,定义rules为空没有权限,通过匹配标签的的rules填充到当前rules中
RBAC企业实战
通过ClusterRole创建通用权限,比如执行命令,删除pode,查看日志,查看名称空间等通用权限,我们将用户创建到某一个统一的名称空间下,对于查看名称空间的通用权限通过ClusterRoleBinding授权给名称空间下所有用户,将不同权限,通过rolebinding 在特定名称空间下单独授权,这样可以实现不同用户不同权限
Cluster (克拉 施特儿)
authorization (凹突入 Z什)
rules (如揉s)
resources (瑞 扫 色思)
verbs (文儿 不死)
watch (我吃)
subjects (纱布 杰克特)
roleRef (肉哦 睿夫 )
view (唯有)
aggregationRule (挨格瑞 给讯 如揉)
clusterRoleSelectors (克拉斯 如揉 史莱克特)
matchLabels (马斯 雷柏)
reconcile (rai肯 赛哦)
第14章 K8s高级篇-云原生存储及存储进阶
示例
什么是StorageClass和CSI
StorageClass是存储类,用于动态PV的管理,会自动的创建、删除PV
CSI是k8s提供的存储接口,存储厂商可以通过这个接口提供一个驱动,然后StorageClass只需要配置该驱动,驱动器会代替StorageClass管理存储
StorageClass动态存储
定义kind类型是StorageClass,然后定义provisioner就是使用的存储驱动是什么,后面就是针对该驱动进行一些配置,最后定义reclaimPolicy回收策略,动态存储默认都是Delete
然后配置pvc,指定storageClassName就是StorageClass的名称,之后在服务内配置此pvc
扩容
扩容需要修改pvc的storage,他会自动扩容
StorageClass (死都儿记 Class)
Rook Operator (Rook 哦噗 瑞德尔)
Rook Discover (Rook 的士 尬乌尔)
Rook Agent (Rook A金特)
Flex (弗来 克斯)
successfully (谁可赛 弗雷)
failureDomain (匪欧 叶儿 德迷)
provisioner (pro 为什呢)
parameters (婆儿 米德死)
allowVolumeExpansion (奥老 Volume A克斯 攀什)
reclaimPolicy (瑞 奎A Policy)
claimName (奎木 Name)
volumeClaimTemplates (我有木 奎木 谈普雷次)
snapshot (思奶噗 夏儿特)
csidriver (csi 拽文儿)
dataSource (data 搜而死)
第15章 K8s高级篇-中间件容器化及Helm
示例
Helm
Helm是有包的概念的,这个包来自于仓库,分别是官方helm仓库和第三方仓库bitnami
Helm v3 Chart目录层级解析
通过helm 命令create 选项指定名称,创建一个Chart,可以看到整个chart的层级结构,chart目录是依赖文件,Chart.yaml文件是当前chart的基本信息,templates是模板,values.yaml是配置全局变量或者一些参数
Helm内置变量的使用
Release.Name: 实例的名称,helm 安装时指定的名字
Release.Namespace: 应用实例的命名空间
Release.Is Up grade: 实例的操作是更新或者回滚,值就会被置为true
Release.IsInstall: 实例的操作是安装,则这边变量被置为true
Release.Revision: 修订的版本号,每次升级回滚都会增加1
Helm常用函数的使用
trim 删除任一侧空格
trimAll 删除给定的字符
quote 给字符添加双引号
squote 给字符添加单引号
Helm逻辑控制
If/Else 判断条件,执行下面的操作
with 相当于切换目录,从当前相对目录找,不需要在写完整路径
range 循环的取值,对于列表通过 点 获取取出的值,对于字典,需要定义刀乐key和刀乐Values获取取出的值
helm基础命令
helm pull 下载包
helm create 创建包
helm install 安装包
helm list -n public-service 查看
helm get values 查看安装参数
helm upgrade 更新,也可以跟上--install参数直接安装
helm delete 删除
helm search repo zookeeper 搜索包
bitnami (呗 纳米)
Operator (哦噗 瑞德尔)
repo (瑞 泼嗷)
values (喔 呦)
upgrade (啊噗 格瑞 的)
Chart (且儿 特)
Release (re 丽思)
trim (踹 木)
quote (扣哦 特)
squote (思 扣哦 特)
upper (啊 噗儿)
lower (搂 乌尔)
replace (瑞 普雷斯)
Else (哎 欧斯)
with (外 丝)
range (润 记)
dry (拽 一)
search (舍儿 尺)
第16章 K8s运维篇-K8s容器日志收集
示例
K8s需要收集哪些日志
需要收集系统日志, k8s组件日志,还有我们业务程序的日志
收集日志常用的技术栈
E L K技术栈: Elasticsearch 加 Logstash 加 Kibana
E F K技术栈: Elasticsearch 加 Fluentd 加 Kibana
ES+Fluentd+Kibana架构解析
给需要收集日志的节点打上标签,通过DaemonSet的形式部署Fluentd到需要收集日志的节点上,通过配置为HostPath类型的volume,把宿主机的目录挂载到Fluentd容器当中,这样Fluentd可以把日志给采集走了,Fluentd在配置文件中指定一个es集群的地址,把收集到的日志交给es,然后在kibana展示
Fluentd的configmap配置中input.conf文件中指定了需要收集的日志路径,output.conf文件指定了日志输出到什么地方,host 和 port 可以定义需要输出到的主机地址和端口号
Filebeat+Kafka+Logstash+ES架构解析
主要是为了使用Filebeat收集未输出到控制台的容器日志,通过在pode中启动两个容器,一个是业务程序,一个是Filebeat,然后配置为EmptyDir类型的volume,就可以实现两个容器目录共享,这个时候Filebeat就可以采集到程序容器的日志文件,然后将它输出到kafak消息队列里面去,然后Logstash就会去获取到kafka里面的消息,进行数据的解析,之后 Logstash 会把数据存储到es当中,之后再通过kibana展示
Logstash的configmap配置logstash.conf 文件中input指定数据的输出,output指定数据的来源,input的时候通过插件比如kafka来收集,或者收集的时候通过插件进行文本处理,然后output的时候可以通过if判断数据,然后输出到不同的es,不同的index索引
filebeat的configmap配置filebeat.yml文件中有filebeat.input和output.kafka配置,可以指定需要收集的日志路径,需要输出到什么主机和 topic
Fluentd (否楼 恩特)
第20章 K8s运维篇-服务发布Ingress
示例
ingress生产级高可用架构
通过 HostNetwork形式搭建 ,HostNetwork是容器直接在宿主机上启动一个服务,在宿主机上看到一个nginx进程,不会经过多次代理,直接使用的宿主机的网络
ingress Redirect域名丛定向
在ingress中的metadata中定义annotations使用permanent-redirect参数,直接指定需要丛定向的域名即可
dnsPolicy (dns 抛了谁一)
ClusterFirstWithHostNet (克拉斯特儿 菲尔史特 外丝 HostNet)
expose (A克斯 颇似)
Redirect (瑞得 rai特)
Annotations (A那 退深思)
permanent (破 们恩特)
Rewrite (瑞 (rai)润特)
snippet (舍 拜特)
Prometheus
示例
什么是Prometheus
开源的系统监控和报警框架,本身是一个 T S D B 时序列数据库
Prometheus架构
Prometheus Server 抓取和存储时间序列数据,提供数据的查询和告警策略的配置
Alertmanager 用于告警的组件,根据路由配置,将告警信息发送给指定的人或组
Grafana 用于展示数据
Exporter 用来采集未提供metrics接口应用监控数据
什么是ServiceMonitor
Prometheus的配置文件叫 Prometheus点yml文件配置了一些监控的目标,或者告警的策略,使用Operator 安装的时候,设计出来了一个自定义的资源叫做 ServiceMonitor,用来通过k8s的 service的自动发现功能,就是selector 就是来匹配service 从而获取到监控目标,然后解析到Prometheus点yml配置中
云原生和非云原生应用的监控流程
云原生的应用,ServiceMonitor的selector去找云原生的应用暴露出来的service提供的metrics接口
非云原生的应用,ServiceMonitor的selector就去找Exporter service提供metrics接口
Prometheus黑盒监控
白盒监控:程序内部的一些指标
黑盒监控:在用户的角度看到的东西,比较关注现象,比如网站打开慢,网站打不开
通过blackbox这个exporter实现
Alertmanager配置文件解析
Prometheus的service产生了一些告警,他会把alerts传给 Alertmanager ,那么之后Alertmanager会根据自己的路由配置,把指定的告警发送给指定的媒介
Global: 全局配置,通用配置,比如邮件通知的账号、密码
Templates: 自定义模板的位置
Route: 告警路由配置,将不同分组的告警发送给不同的收件人,可以有子Route,越精细优先级越高,通过匹配分组,来决定告警分发给哪个收件人
Inhibit_rules: 告警抑制,宿主机挂了,服务告警就没必要发送了,防止告警风暴
Receivers: 告警收件人配置
告警实践:PrometheusRule
prometheus的配置文件会指定一个 rule_files,就是告警规则的一个配置文件,在operator 当中不需要去维护一个 rule_files 指定的告警规则的文件,而是通过 PrometheusRule 加载到的
PromQL (噗ruang木 QL)
Metrics (卖缺儿 克丝)
Alertmanager (阿勒特 买内鸡儿)
Exporter (艾克斯 泼 特尔)
Monitor (Service 猫内特 )
Blackbox (布拉克 爆克斯)
targets (塔儿 给 吃)
params (泼 瑞慕斯)
replacement (瑞普雷 斯闷特)
firing (发页 音)
resolved (瑞 绕福特)
route (如特)
Inhibit_rules (音 嘿 拜特 如肉丝)
Receivers (瑞 C 味儿斯)
Receiver (瑞 C 味儿)
continue (肯忒牛)
match (麦尺)
wait (韦特)
interval (音特 嗡)
repeat (瑞皮特)
cicd
示例
什么是DevOps和CICD
DevOps是重视开发人员和运维人员之间沟通合作的文化、协作和整合
C I / C D是DevOps中尤为重要的一个环节,通过在应用开发阶段引入自动化工具,来频繁向客户交付应用的方法
主要分为了三个方面
持续集成: 开发人员频繁地将代码更改合并到分支或主干中
持续交付: 代码提交到开发环境,然后开发环境测试没有问题,把代码合并到master分支,也就是说这个代码已经可以随时发布到生产环境中
持续部署: 可以自动将应用发布到生产环境中
什么是流水线Pipeline
把比较复杂的工作,拆分成不同的单元,每个单元只负责自己的事情,比如提交、编译、部署等
声明式 Pipeline 语法
声明式流水线必须包含在一个 Pipeline 块中
Agent: 执行的位置,可以在顶层全局定义,或者在不同阶段分别定义,可以使用docker或者kubernetes 来执行
Post: 流水线结束后的进一步处理,比如错误通知等
Stages: 包含一个或多个 stage 指令
Steps: 真正执行的指令
Environment: 流水线中配置的一些环境变量
Options: 流水线支持很多内置指令
Parameters: 在触发流水线时应该提供的参数列表
Triggers: 实现自动触发流水线执行任务
Input: 实现在流水线中进行交互式操作
When: 允许流水线根据给定的条件决定是否应该执行该 stage
Parallel: 实现并发构建
Jenkinsfile凭证管理
credentials函数可以获取凭证,比如加密文本,加密文件,用户名密码
基于K8s的DevOps平台设计
开发人员向gitlab提交代码,gitlab触发jenkins去构建,这个jenkins会连接到k8s上,然后k8s会创建一个pode,这个pod会做为我们jenkins的一个slave,那么这个slave包含了我们需要构建,发版,编译,所用的工具,他每一个工具都是一个容器,这个slave通过jnlp是Java 网络加载协议和jenkins master节点进行通讯,编译完成后通过 Dockerfile 生成镜像,将镜像推送到镜像仓库,jenkins 控制 Kubernetes 进行最新的镜像部署,流水线结束删除 Jenkins Slave
Jenkins Agent配置
jnlp默认会通过50000端口链接jenkins master,需要打开此端口
Jenkins配置K8s多集群
jenkins会连接到k8s去创建一个slave的pode,所以jenkins需要知道要连接到哪个k8s去创建,通过Credentials 添加的Kubernetes 证书,来添加k8s集群,最新版本好像需要r b a c权限和jenkins地址
Sections (赛克 寻思)
agent any (A 巾特 爱内)
stages (死得 基思)
stage (死得 基)
steps (斯 代 普斯)
junit (酒 奈特)
Directives (戴睿 科特思)
Environment (音歪有 门特)
Options (欧普 讯)
Parameters (铺歪 莫特儿)
Triggers (催嗝儿 斯)
When (问嗯)
Parallel (派尔 老欧 )
Credentials (奎蛋翘死)
Blue Ocean (不露 欧讯)
20230711
示例
# 面试不要不懂装懂,不会就是不会,不可能每个人都接触过所有的知识!
## 1. 基础问题
### 1.1 Service是怎么关联Pod的?(课程Service章节)
答:创建Pod是都会定义Pod的便签,比如role=frontend,Service通过Selector字段匹配该标签即可关联至该Pod,Pod和Service需要在同一个namespace,[中文文档](https://kubernetes.io/zh/docs/concepts/services-networking/connect-applications-service/)。
### 1.2 HPA V1 V2的区别
答:HPA v1为稳定版自动水平伸缩,只支持CPU指标。V2为beta版本,分为v2beta1(支持CPU、内存和自定义指标),v2beta2(支持CPU、内存、自定义指标Custom和额外指标ExternalMetrics),从k8s 1.11之后,度量指标的采集依赖metrics-server,弃用了heapster,[中文文档](https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/)。
### 1.3 Pod生命周期(课程Pod章节)
答:
Pod创建:
1. API Server 在接收到创建pod的请求之后,会根据用户提交的参数值来创建一个运行时的pod对象。
2. 根据 API Server 请求的上下文的元数据来验证两者的 namespace 是否匹配,如果不匹配则创建失败。
3. Namespace 匹配成功之后,会向 pod 对象注入一些系统数据,如果 pod 未提供 pod 的名字,则 API Server 会将 pod 的 uid 作为 pod 的名字。
4. API Server 接下来会检查 pod 对象的必需字段是否为空,如果为空,创建失败。
5. 上述准备工作完成之后会将在 etcd 中持久化这个对象,将异步调用返回结果封装成 restful.response,完成结果反馈。
6. API Server 创建过程完成,剩下的由 scheduler 和 kubelet 来完成,此时 pod 处于 pending 状态。
7. Scheduler选择出最优节点。
8. Kubelet启动该Pod。
Pod删除:
1. 用户发出删除 pod 命令
2. 将 pod 标记为“Terminating”状态
监控到 pod 对象为“Terminating”状态的同时启动 pod 关闭过程
endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除
Pod执行PreStop定义的内容
3. 宽限期(默认30秒)结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号
4. Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作
### 1.4 Kubernetes Master节点高可用(课程Master节点和Node节点章节)
答:Kube-APIServer为无状态服务,可以启动多个,通过负载均衡进行轮训。ControllerManager和Scheduler为有状态服务,多节点启动会进行选主,主节点信息保存在kube-system命名空间下的对应名称的endpoint中
### 1.5 QoS(课程QoS章节)
答: 最高级别:Guaranteed节点资源不够时最后一个被杀掉, Burstable第二个被杀掉,BestEffort第一个被杀掉
### 1.6 flannel和calico(课程安装章节)
答:如果没有用过flannel可以直接说没有用过flannel,都是用的calico,因为calico性能强大,并且配置简单。Flannel的host-gw虽然性能好,但是只能用于大二层网络,vxlan对内核要求高,并且flannel不支持网络策略,所以采用calico。因为公司和公有云网络环境不支持BGP,所以目前采用的都是IPIP模式。
### 1.7 Helm优点(课程Helm章节)
答:大型项目更加方便管理,可以一键创建一个环境,可以对整个项目进行版本升级、回滚,部署更加方便。
### 1.8 公司的架构是什么样的?
答:我们的架构是这样的,三台master,三台e t c d,e t c d和master没有放在一起。然后在指定的节点上部署了ingress nginx,然后外部有个网关(可以选择性说网关是硬件设备F5或者DMZ的nginx,或者公有云的LB)连接到了k8s ingress节点的80和433,然后有个通配符域名指向了ingress,在ingress上面又做的分发。
## 2. 日志监控
### 2.1 容器内日志怎么采集的?(课程日志采集章节)
答:容器内日志我们是使用filebeat进行采集的,filebeat以sidecar的形式和业务应用运行在同一个Pode内,使用emptyDir进行日志文件的共享。
### 2.2 Fluentd说一下
答:Fluentd配置简单,并且Docker日志一般是j son输出,使用fluentd收集更加方便,当然filebeat也是可以采集节点日志的。
### 2.3 日志的索引(课程日志采集章节)
答:为了更快的查询日志,一般我们会根据集群、命名空间、资源名称进行添加索引。
### 2.4 e t c d怎么监控的?(课程自带metrics接口应用的监控)
答:etcd属于云原生应用,自带了metrics接口,可以直接请求metrics接口即可获取到监控数据,一般监控etcd的状态、leader是否正常、选择次数、选主失败次数、集群延迟、落盘延迟等。(此问题可以根据监控项自行补充)
### 2.5 黑盒监控blackbox(课程黑盒监控)
答:黑盒监控可以监控http、tcp的监控状态、延迟、解析速度、证书到期时间等指标,可以根据课程的监控图自行补充。
### 2.6 状态码监控
答:可以这么回答,我们使用的是ingress,ingress也是用Prometheus监控的,可以监控到某个应用的请求状态,比如多个200、502、403等,课程ingress监控章节。
### 2.7 你之前是怎么监控K8S的,监控哪些指标(课程监控章节)
答:我是利用Prometheus监控的,主要是监控宿主机的指标、Pod指标,比如内存CPU使用率,是否有重启这类的。然后也使用了黑盒监控,监控应用是否是正常的等。在k8s的监控和传统架构区别不大,该监控的还要监控,可以想一下之前是怎么监控的,那在k8s里面同样也可以监控。
### 2.8 你之前是怎么收集K8S日志的,有哪些方案
答:可以回答使用filebeat进行收集的,因为filebeat比较轻量级,并且配置比较简单。同时也支持以sidecar的方式部署到Pod里面,这样同时也能收集Pod容器内的日志。一般会采用filebeat+kafka+logstash+es+kibana这种架构。
## 3. 存储问题
### 3.1 Rook问题(课程rook章节)
答:Rook现在已经毕业了,之前虽然没有毕业,但是对ceph的支持已经是stable了,并且rook降低了ceph的学习成本,几乎不用运维,所以我们采用了Rook。使用Rook操作ceph扩容也是非常简单的,只需要更改rook创建ceph集群的资源文件即可。
### 3.2 如何对接外部CEPH(课程volume和动态存储章节)
答:对接的方式有很多,使用Rook可以对接外部ceph,使用volume、pvc、storageClass和CSI插件都可以对接外部ceph。
### 3.3 生产环境的pv回收策略如何选择?
答:目前pv的回收策略分为recycle、delete、retain,具体用法可以参考课程的pv章节。其中recycle(相当于对数据目录进行rm -rf /xxx/* ,进行回收的时候会创建一个Pod进行rm操作)将被官方使用动态存储供应(dynamic provisioning)逐步替代。所以面试遇到这类问题,可以着重回答delete和retain。其中Delete回收策略一般用于动态存储,比如ceph、GFS这类的,也就是通过StorageClass进行管理创建的pv,Delete的策略也是StorageClass的默认策略,因为当一个项目用到存储时,会通过pvc或者volumeTemplateClaim申请存储,然后后端存储会自动创建pv,所以当你删除pvc或者pv时,就认为你已经不需要这个存储了,就会触发自动删除pv,防止造成存储池存储过多无人使用的垃圾pv。而静态文件建议使用Retain,比如NFS、NAS这类的,因为这些文件一般都是手动管理的,所以最好是尽量保持这些文件的可用性,就算不用了,也是可以根据目录名称进行手动删除。所以retain和delete是用的比较多的。
### 3.4 K8S持久化对接过哪些储存,为什么要选择它?(课程存储章节)
答:可以写自己的实际情况,不能没有做过就胡说。比如常见的NFS和ceph,可以回答CEPH,因为ceph是比较常用的分布式存储,支持文件存储、块存储和对象存储,而且性能还是比较好的。GFS和NFS可以不说,因为GFS可能会被淘汰,NFS是单点的。
## 4. 大厂面试题
### 4.1 介绍下工作经历,从事过哪些和K8s相关的工作
答:真是的工作要说,你在学习过程中做的一些项目或者经验都可以说一下,但是自己没有经过手的最好不要说,防止露馅。比如高可用集群搭建和维护、Prometheus监控的使用、CICD的建设等。要往自己会的方向引导。
### 4.2 主要语言是什么?平时这些项目上云有哪些注意的点
答:主要考察的是你对项目上云以及对某个语言的发版流程是否熟悉。比如Java语言是mvn编译,go语言是go build,nodejs是npm run build等。你可以说一下自己做过的容器化项目,比如Java语言的或者是nodejs。注意事项就是一个应用上云的步骤的一些细节。比如如何发版、如何回滚、如何配置QoS和健康检查等。
### 4.3 有遇到过容器的OOM的问题吗?怎么处理的?
答:遇到OOM有两种情况,第一种情况是这个程序确实需要4Gi(假设)内存,但是你的limit配置只给了3Gi,这样就会有OOM。另外一种情况是程序本身是有内存溢出的,可能没有做好垃圾回收,导致内存一直往上涨,这样的可能需要开发人员加上相应的垃圾回收,还有一种程序内存溢出是因为limit设置的太低导致不能正常的垃圾回收,比如一个程序正常运行需要3Gi,但是垃圾回收可能也需要占用内存,所以此时给3Gi肯定是不行的,一般需要超过3Gi,也就是limit配置要超过程序需求的800M-1Gi。
### 4.4 有状态应用如何上云?
答:有状态应用其实也分为需要存储数据的和不需要存储数据的。如果是有需要存储数据的部署在K8s上,最好有后端可靠的存储支持,比如分布式的ceph或者公有云的存储,最极端的情况是没有后端存储支持,可以采用hostPath挂载,采用固定节点的形式,可以参考csi hostpath,或者storageClass hostPath。而有的有状态应用并不需要存储数据,只是想要有规定的标识符。
### 4.5 解析下CRD和Operator?有没有自己开发过CRD和Operator?
答:operator规范的说是operator = crd+controller,也就是operator可以理解为是一个自定义的控制器,CRD是一个自定义的资源类型,就像我们定义的deployment、service等,这些是官方自带的控制器,CRD则是扩展的资源类型。开发过就说开发过,可以讲一下如何开发的,没有开发过就说没有用到这种场景,目前还没有这个需求,因为一些中间件他们官方已经写好了operator,然后自己公司的项目一键部署使用helm管理的,因为helm比较简单(不会helm这句话不要说)。
### 4.6 什么是CNI?平时K8s集群用的是哪个网络插件?
答:CNI是k8s提出的容器网络接口,相当于一种规范,只要网络厂商的产品符合了这个规范,那么这个网络厂商的产品就能为k8s提供网络管理。常用的有calico、cilium、flannel等,可以回答说现在常用的是calico,因为他部署方便,很多大厂都在用,并且原生支持网络策略,flannel不支持网络策略。
### 4.7 为什么Pod中关于资源有request和limit两个字段?有想过这么设计的原因吗?(课程QoS章节)
答:request是用于程序的最小请求,limit是用于程序的最大请求。另一方面request可以防止节点部署过多的Pod,limit可以防止拖垮节点。
### 4.8 OpenShift和K8s相比有哪些不同?
答:以我个人的理解,openshift是一个企业级的平台,包含了很多开箱即用的东西,比如可以很方便的创建一个Java应用,或者很方面的进行服务发布,他是对k8s进行了一层封装,并且提供了S2I的形式用于应用的构建和发布。而K8s是原生的下一代云计算平台,很多东西都需要自己去维护,比如你想要监控程序,就需要自己去搭建一个Prometheus或者其他的。如果大家对openshift不太熟悉,切记不能说太多openshift的东西。
### 4.9 Pod被调度到一个节点的具体过程?
答:见本页1.3
### 4.10 有了解过istio吗,和springcould有什么区别
答:有过一些了解Istio是Google开源的服务网格,号称可以让开发人员无需关心流量管理方面的代码,只需要关心业务逻辑,可以提高开发效率。而springcloud是专门为Java语言设计,虽然他可以很方面实现流量管理的功能,比如灰度、熔断、负载均衡等,但是也需要开发写少量代码,并且只能Java使用,而istio和语言无关,并且不需要开发写代码。
### 在k8s Jenkins 发布详细流程
答:可以看一下课程流水线设计的文档
# 以上问答只是个人见解,不一定是最好的回答,大家可以自行查阅网上资料。
nginx
nginx默认模式
nginx默认模式
nginx默认模式是Master进程加Worker进程,和apache的prefork模型类似,单个主进程+多个⼯作进程,每个⼯作进程中一个线程 处理客户端的请求
master进程只有一个,负责监听端⼝,接受来⾃web server的请求。
worker进程一般会有多个,每个进程中会嵌⼊一个php解析器,进⾏php代码的处理。
测试vip能够在两个server之间迁移完成)
示例
两个server之间:
vrrp_instance # 名称一致
state # 状态需要分清主备MASTER和BACKUP
virtual_router_id # id号一致
priority # 优先级备份BACKUP的优先级不能高于主MASTER的优先级
authentication # 认证方式和密码一致
virtual_ipaddress # vip地址一致
示例,抢占模式
如果Backup路由器工作在抢占方式下,当它收到VRRP报文后,会将自己的优先级与通告报文中的优先级进行比较。如果自己的优先级比当前的Master路由器的优先级高,就会主动抢占成为Master路由器;否则,将保持Backup状态
server1安装keepalived和tcpdump抓包软件
server1安装keepalived和tcpdump抓包软件
server1编辑配置文件
vrrp_instance VI_1 {
state MASTER # 主的状态设置为MASTER
interface ens33 # 修改网卡名,绑定为当前虚拟路由器使用的物理接口,通过此接口接收报文的通告
virtual_router_id 51 # 虚拟路由器id,双方一致
priority 100 # 优先级100,需要BACKUP优先级高
advert_int 1 # 通告发送间隔必须一致
authentication {
auth_type PASS
auth_pass 12345678
}
virtual_ipaddress { # 配置vip地址
192.168.127.200 dev ens33 lable ens33:0
192.168.127.200 dev ens33 lable ens33:1 # 两个虚拟网卡的名称不能一致