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的解析结构:

..svc.

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也最终会调度失败。