1:如何在 Kubernetes 中实现负载均衡?
2:在生产中,你如何实现 Kubernetes 自动化?
3:你如何扩展 Kubernetes 集群?
4:你能解释 Deployment、ReplicaSets、StatefulSets、Pod、CronJob 的不同用途吗?
5:Kubernetes 如何处理持久性?
6:服务和 ingress 的作用是什么?
7:你何时会使用像 ConfigMap 或 secret 这样的东西?
8:Pod 亲和性作用是什么?
9:你能举例说明何时使用 Init Container 么?
10:什么是 sidecar 容器?你能给出一个用例,说明你为什么要使用它么?
11:在构建和管理生产集群时遇到的主要问题是什么?
12:为什么你会建议公司在云中构建自己的 K8S 集群而不是使用托管服务?
13:什么是 Istio 和 Linkerd?
14:什么是 Kubernetes Operator?
15:kubernetes包含几个组件。 各个组件的功能是什么。组件之间是如何交互的。
16:k8s的pause容器有什么用。是否可以去掉。
17:k8s中的pod内几个容器之间的关系是什么。
18:一个经典pod的完整生命周期。
19:k8s的service和ep是如何关联和相互影响的。
20:详述kube-proxy原理, -个请求是如何经过层层转发落到某个pod.上的整个过程。请求可能来自pod也可能来自外部。
21:rc/rs功能是怎么实现的。详述从API接收到-一个创建rc/rs的请求,到最终在节点上创建pod的全过程,尽可能详细。另外,当-个pod失效时,kubernetes是如何发现并重启另一个pod的?
22:deployment/rs有什么区别。 其使用方式使用条件和原理是什么。
23:cgroup中的cpu有哪几种限制方式。 k8s是如何使用实现request和limit的。
Kubernetes的优势
1.易学:轻量级,简单,容易理解;
2.便携:支持公有云,私有云,混合云,以及多种云平台;
3.可扩展:模块化,可插拔,支持钩子,可任意组合;
4.自修复:自动重调度,自动重启,自动复制。
在项目实战中,贝斯平的技术专家整理了Kubernetes在使用中的一些常见问题,希望对您有所帮助。
01
在K8S集群中出现A节点无法访问B节点上的Pod,怎么办?
如果A节点无法ping通B节点上的Pod的IP地址,则在B节点上执行iptables -P FORWARD ACCEPT,反之则在A节点上执行iptables -P FORWARD ACCEPT即可。
02
在搭建Kubernetes集群过程中,安装了kube-dns插件后,运行一个ubuntu容器,发现容器内无法解析集群外域名,一开始可以解析集群内域名,一段时间后也无法解析集群内域名。
在Kubernetes集群中,kubelet是worker组建,负责管理Pod,根据Kubernetes文档,kubelet默认会从Node的/etc/resolv.conf文件读取DNS服务器地址,使得dnsPolicy是Default的Pod得以继承,kubelet中的—resolv-conf参数可以指定这个配置文件的地址。在Ubuntu 18.04中,将这个参数设置为systemd-resolved的DNS服务器配置文件/run/systemd/resolve/resolv.conf,Pod就会继承真正的外部DNS服务器。
03
DNS解析慢或超时如何解决?
DNS的解析结构:
myapp.default.svc.cluster.local
解析慢的时候或者解析超时的时候:
curl myapp.default.svc.cluster.local
这种时候可能会出现解析慢或者解析超时的情况;
curl myapp.default.svc.cluster.local.
这时在最后加上一个 “.” 解析就没有问题了
04
Pod无法成功创建,describe查看原因,显示:mount failed。
原因:指定与块设备不一致的文件系统类型。
05
Kubernetes 新加了个node,状态Ready, 但调度过去的任务都执行异常
Kubernetes集群原来机器的ip都在en1上,flannel节点启动设置的网卡都在en1, 新加的这台节点ip却在en2上,以en1启动则失败。
此时需要查看flannel的配置:
kubectl -n kube-system get ds kube-flannel-ds -o yaml
containers:
- args:
- —ip-masq
- —kube-subnet-mgr
- —iface=en1
06
Kubernetes 如何清空节点?
排干节点:kubectl drain 节点名称 —delete-local-data —force —ignore-daemonsets
删除节点:kubectl delete node 节点名称
07
KubernetesPod调度失败问题(INSUFFICIENT PODS)
Kubernetes的node默认最大pod数量为110个,所有node都达到110个时无法再调度,出现如下报错信息:
0/3 nodes are available: 1 node(s) had taints that the pod didn’t tolerate, 2 Insufficient pods
解决办法:
修改/etc/sysconfig/kubelet配置文件,添加—max-pods配置,然后重启kubelet服务,修改后文件内容如下:
KUBELET_EXTRA_ARGS=”—fail-swap-on=false —max-pods=300”
08
请求服务时返回⼤量502、503 错误该如何处理?
某些 java 服务更新时,由于健康检查设置的预估启动时间过短,会导致健康检查不通过,服务更新失败,此时访问服务就会有异常。⽽ nginx 配置默认设置了max_fails=1 (请求失败的最⼤尝试次数), fail_timeout=10s (请求失败的超时时长),服务异常时,会有 10s 的时间将后端节点标记为不可⽤,请求服务时就会返回 502、503 错误。
解决⽅案(任选一个):
1、将 nginx 的 max_fails 取值增大,增加请求失败的尝试次数,例如:配置的 upstream 字段为 max_fails=10 、 fail_timeout=10s ;
2、将健康检查的预估启动时间增长,避免因预估启动时间过短而导致健康检查不通过。
09
Node的隔离和恢复
如果A节点无法ping通B节点上的Pod的IP地址,则在B节点上执行iptables -P FORWARD ACCEPT,反之则在A节点上执行iptables -P FORWARD ACCEPT即可。
在硬件升级、硬件维护等情况下,需要将某些Node进行隔离,脱离Kubernetes集群的调度范围。Kubernetes提供了一种机制,既可以将Node纳入调度范围,也可以将Node脱离调度范围。
创建配置文件unschedule_node.yaml,在spec部分指定unschedulable为true:
apiVersion: v1
kind: Node
metadata:
name: kubernetes-minion1
labels:
kubernetes.io/hostname: kubernetes-minion1
spec:
unschedulable: true
然后,通过kubectl replace命令完成对Node状态的修改:
$ kubectl replace -f unschedule_node.yaml
nodes/kubernetes-minion1
查看Node的状态,可以观察到在Node的状态中增加了一项SchedulingDisabled:
$ kubectl get nodes
NAME LABELS STATUS
kubernetes-minion1 kubernetes.io/hostname=kubernetes-minion1 Ready, SchedulingDisabled
对于后续创建的Pod,系统将不会再向该Node进行调度。另一种方法是不使用配置文件,直接使用kubectl patch命令完成:
$ kubectl patch node kubernetes-minion1 -p ‘{"spec":{"unschedulable":true}}’
需要注意的是,将某个Node脱离调度范围时,在其上运行的Pod并不会自动停止,管理员需要手动停止在该Node上运行的Pod。
同样,如果需要将某个Node重新纳入集群调度范围,则将unschedulable设置为false,再次执行kubectl replace或kubectl patch命令就能恢复系统对该Node的调度。
10
将Pod调度到指定的Node
我们知道,Kubernetes的Scheduler服务(kube-scheduler进程)负责实现Pod的调度,整个调度过程通过执行一系列复杂的算法最终为每个Pod计算出一个最佳的目标节点,这一过程是自动完成的,我们无法知道Pod最终会被调度到哪个节点上。有时我们可能需要将Pod调度到一个指定的Node上,此时,我们可以通过Node的标签(Label)和Pod的nodeSelector属性相匹配,来达到上述目的。
首先,我们可以通过kubectl label命令给目标Node打上一个特定的标签,下面是此命令的完整用法:
kubectl label nodes =
这里,我们为kubernetes-minion1节点打上一个zone=north的标签,表明它是“北方”的一个节点:
$ kubectl label nodes kubernetes-minion1 zone=north
NAME LABELS STATUS
kubernetes-minion1 kubernetes.io/hostname=kubernetes-minion1,zone=north Ready
上述命令行操作也可以通过修改资源定义文件的方式,并执行kubectl replace -f xxx.yaml命令来完成。
然后,在Pod的配置文件中加入nodeSelector定义,以redis-master-controller.yaml为例:
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: master
image: kubeguide/redis-master
ports:
- containerPort: 6379
nodeSelector:
zone: north
运行kubectl create -f命令创建Pod,scheduler就会将该Pod调度到拥有zone=north标签的Node上去。
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE NODE
redis-master-f0rqj 1/1 Running 0 19s kubernetes-minion1
如果我们给多个Node都定义了相同的标签(例如zone=north),则scheduler将会根据调度算法从这组Node中挑选一个可用的Node进行Pod调度。
这种基于Node标签的调度方式灵活性很高,比如我们可以把一组Node分别贴上“开发环境”“测试验证环境”“用户验收环境”这三组标签中的一种,此时一个Kubernetes集群就承载了3个环境,这将大大提高开发效率。
需要注意的是,如果我们指定了Pod的nodeSelector条件,且集群中不存在包含相应标签的Node时,即使还有其他可供调度的Node,这个Pod也最终会调度失败。