kubernetes常见问题

1.k8s是什么,请说出你的了解?

Kubenetes是一个针对容器应用,进行自动部署,弹性伸缩和管理的开源系统。主要功能是生产环境中的容器编排。
K8S是Google公司推出的,它来源于由Google公司内部使用了15年的Borg系统,集结了Borg的精华。

2.K8s架构的组成是什么?

1、Master节点(默认不参加实际工作):
Kubectl:客户端命令行工具,作为整个K8s集群的操作入口;
Api Server:在K8s架构中承担的是“桥梁”的角色,作为资源操作的唯一入口,它提供了认证、授权、访问控制、API注册和发现等机制。客户端与k8s群集及K8s内部组件的通信,都要通过Api Server这个组件;
Controller-manager:负责维护群集的状态,比如故障检测、自动扩展、滚动更新等;
Scheduler:负责资源的调度,按照预定的调度策略将pod调度到相应的node节点上;
Etcd:担任数据中心的角色,保存了整个群集的状态;
2、Node节点:
Kubelet:负责维护容器的生命周期,同时也负责Volume和网络的管理,一般运行在所有的节点,是Node节点的代理,当Scheduler确定某个node上运行pod之后,会将pod的具体信息(image,volume)等发送给该节点的kubelet,kubelet根据这些信息创建和运行容器,并向master返回运行状态。(自动修复功能:如果某个节点中的容器宕机,它会尝试重启该容器,若重启无效,则会将该pod杀死,然后重新创建一个容器);
Kube-proxy:Service在逻辑上代表了后端的多个pod。负责为Service提供cluster内部的服务发现和负载均衡(外界通过Service访问pod提供的服务时,Service接收到的请求后就是通过kube-proxy来转发到pod上的);
container-runtime:是负责管理运行容器的软件,比如docker

3.容器和主机部署应用的区别是什么?

容器的中心思想就是秒级启动;一次封装、到处运行;这是主机部署应用无法达到的效果,但同时也更应该注重容器的数据持久化问题。
另外,容器部署可以将各个服务进行隔离,互不影响,这也是容器的另一个核心概念。

4.请你说一下kubenetes针对pod资源对象的健康监测机制?

livenessProbe探针
可以根据用户自定义规则来判定pod是否健康,如果livenessProbe探针探测到容器不健康,则kubelet会根据其重启策略来决定是否重启,如果一个容器不包含livenessProbe探针,则kubelet会认为容器的livenessProbe探针的返回值永远成功。
ReadinessProbe探针
同样是可以根据用户自定义规则来判断pod是否健康,如果探测失败,控制器会将此pod从对应service的endpoint列表中移除,从此不再将任何请求调度到此Pod上,直到下次探测成功。
startupProbe探针
启动检查机制,应用一些启动缓慢的业务,避免业务长时间启动而被上面两类探针kill掉,这个问题也可以换另一种方式解决,就是定义上面两类探针机制时,初始化时间定义的长一些即可。
Exec:通过执行命令的方式来检查服务是否正常,比如使用cat命令查看pod中的某个重要配置文件是否存在,若存在,则表示pod健康。反之异常。
Httpget:通过发送http/htps请求检查服务是否正常,返回的状态码为200-399则表示容器健康(注http get类似于命令curl -I)。
tcpSocket:通过容器的IP和Port执行TCP检查,如果能够建立TCP连接,则表明容器健康,这种方式与HTTPget的探测机制有些类似,tcpsocket健康检查适用于TCP业务。

5.K8s中镜像的下载策略是什么?

可通过命令“kubectl explain pod.spec.containers”来查看imagePullPolicy这行的解释。
K8s的镜像下载策略有三种:Always、Never、IFNotPresent;
Always:镜像标签为latest时,总是从指定的仓库中获取镜像;
Never:禁止从仓库中下载镜像,也就是说只能使用本地镜像;
IfNotPresent:仅当本地没有对应镜像时,才从目标仓库中下载。
默认的镜像下载策略是:当镜像标签是latest时,默认策略是Always;当镜像标签是自定义时(也就是标签不是latest),那么默认策略是IfNotPresent。

6.pod的重启策略是什么

可以通过命令“kubectl explain pod.spec”查看pod的重启策略。(restartPolicy字段)
Always:但凡pod对象终止就重启,此为默认策略。
OnFailure:仅在pod对象出现错误时才重启

7. Service这种资源对象的作用是什么?

用来给相同的多个pod对象提供一个固定的统一访问接口,常用于服务发现和服务访问。

8.版本回滚相关的命令?

[root@master httpd-web]# kubectl apply -f httpd2-deploy1.yaml  --record  #运行yaml文件,并记录版本信息;
[root@master httpd-web]# kubectl rollout history deployment httpd-devploy1  
#查看该deployment的历史版本
[root@master httpd-web]# kubectl rollout undo deployment httpd-devploy1 --to-revision=1    
#执行回滚操作,指定回滚到版本1
#在yaml文件的spec字段中,可以写以下选项(用于限制最多记录多少个历史版本):spec:  revisionHistoryLimit: 5            
#这个字段通过 kubectl explain deploy.spec  命令找到revisionHistoryLimit   <integer>行获得

9.标签与标签选择器的作用是什么?

标签:是当相同类型的资源对象越来越多的时候,为了更好的管理,可以按照标签将其分为一个组,为的是提升资源对象的管理效率。
标签选择器:就是标签的查询过滤条件。目前API支持两种标签选择器:
基于等值关系的,如:“=”、“”“”、“!=”(注:“”也是等于的意思,yaml文件中的matchLabels字段);基于集合的,如:in、notin、exists(yaml文件中的matchExpressions字段);
注:in:在这个集合中;notin:不在这个集合中;exists:要么全在(exists)这个集合中,要么都不在(notexists);

10.查看标签的方式?

kubectl get node --show-labels
kubectl get pod --show-labels

11.添加、修改、删除标签的命令?

kubectl label node node-1 app=nginx
kubectl label node node-1 app=mycat --overwrite
kubectl label node node-1 app-

12.描述一下pod的生命周期有哪些状态?

Pending:表示pod已经被同意创建,正在等待kube-scheduler选择合适的节点创建,一般是在准备镜像;
Running:表示pod中所有的容器已经被创建,并且至少有一个容器正在运行或者是正在启动或者是正在重启;
Succeeded:表示所有容器已经成功终止,并且不会再启动;
Failed:表示pod中所有容器都是非0(不正常)状态退出;
Unknown:表示无法读取Pod状态,通常是kube-controller-manager无法与Pod通信。

13.创建一个pod的流程是什么?

1) 客户端提交Pod的配置信息(可以是yaml文件定义好的信息)到kube-apiserver;
2) Apiserver收到指令后,通知给controller-manager创建一个资源对象;
3) Controller-manager通过api-server将pod的配置信息存储到ETCD数据中心中;
4) Kube-scheduler检测到pod信息会开始调度预选,会先过滤掉不符合Pod资源配置要求的节点,然后开始调度调优,主要是挑选出更适合运行pod的节点,然后将pod的资源配置单发送到node节点上的kubelet组件上。
5) Kubelet根据scheduler发来的资源配置单运行pod,运行成功后,将pod的运行信息返回给scheduler,scheduler将返回的pod运行状况的信息存储到etcd数据中心。

14.删除一个Pod会发生什么事情?

Kube-apiserver会接受到用户的删除指令,默认有30秒时间等待优雅退出,超过30秒会被标记为死亡状态,此时Pod的状态Terminating,kubelet看到pod标记为Terminating就开始了关闭Pod的工作;

15.k8s集群外流量怎么访问Pod?

可以通过Service的NodePort方式访问,会在所有节点监听同一个端口,比如:30000,访问节点的流量会被重定向到对应的Service上面。

16.k8s数据持久化的方式有哪些?

EmptyDir(空目录):没有指定要挂载宿主机上的某个目录,直接由Pod内保部映射到宿主机上。类似于docker中的manager volume。
Hostpath:将宿主机上已存在的目录或文件挂载到容器内部。类似于docker中的bind mount挂载方式。这种数据持久化方式,运用场景不多,因为它增加了pod与节点之间的耦合。
PersistentVolume(简称PV):基于NFS服务的PV,也可以基于GFS的PV。它的作用是统一数据持久化目录,方便管理。

17.kube-apiserver和kube-scheduler的作用是什么?

kube -apiserver遵循横向扩展架构,是主节点控制面板的前端。这将公开Kubernetes主节点组件的所有API,并负责在Kubernetes节点和Kubernetes主组件之间建立通信。
kube-scheduler负责工作节点上工作负载的分配和管理。因此,它根据资源需求选择最合适的节点来运行未调度的pod,并跟踪资源利用率。它确保不在已满的节点上调度工作负载。

18.Replica Set 和 Replication Controller之间有什么区别?

Replica Set 和 Replication Controller几乎完全相同。它们都确保在任何给定时间运行指定数量的pod副本。不同之处在于复制pod使用的选择器。Replica Set使用基于集合的选择器,而Replication Controller使用基于权限的选择器。

19.kubernetes 认证

kubernetes 提供了多种认证方式,比如客户端证书,静态token,静态密码文件,ServiceAccountTokens等等。你可以同时使用一种或多种认证方式。只要通过任何一个都被认作是认证通过。

20.kube-scheduler工作原理,多少节点对外提供服务

根据各种调度算法将 Pod 绑定到最合适的工作节点
预选(Predicates):输入是所有节点,输出是满足预选条件的节点。kube-scheduler根据预选策略过滤掉不满足策略的Nodes。例如,如果某节点的资源不足或者不满足预选策略的条件如“Node的label必须与Pod的Selector一致”时则无法通过预选。
优选(Priorities):输入是预选阶段筛选出的节点,优选会根据优先策略为通过预选的Nodes进行打分排名,选择得分最高的Node。例如,资源越富裕、负载越小的Node可能具有越高的排名。

21.集群使用的网络方案,pod如何和node网络通信的

Flannel:使用vxlan技术为各节点创建一个可以互通的Pod网络,使用的端口为UDP 8472(需要开放该端口,如公有云AWS等)。flanneld第一次启动时,从etcd获取配置的Pod网段信息,为本节点分配一个未使用的地址段,然后创建flannedl.1网络接口(也可能是其它名称,如flannel1等)。flannel将分配给自己的Pod网段信息写入 /run/flannel/subnet.env文件,docker后续使用这个文件中的环境变量设置docker0网桥,从而从这个地址段为本节点的所有Pod容器分配IP。

22.k8s集群节点需要关机维护,需要怎么操作

驱逐 node 节点上 pod

$ kubectl drain k8s-node-01 --force --ignore-daemonsets

关机$ init 0

23.生产中碰到过什么问题,故障排查思路,如何解决的

Pod 故障归类
Pod状态 一直处于 Pending
Pod状态 一直处于 Waiting
Pod状态 一直处于 ContainerCreating
Pod状态 处于 ImagePullBackOff
Pod状态 处于 CrashLoopBackOff
Pod状态 处于 Error
Pod状态 一直处于 Terminating
Pod状态 处于 Unknown

Pod 排查故障命令

# 查看 Pod 配置是否正确
kubectl get pod <pod-name> -o yaml
 # 查看 Pod 详细事件信息
kubectl describe pod <pod-name>
 # 查看容器日志
kubectl logs <pod-name> [-c <container-name>]

Pod 故障问题与排查方法

Pod 一直处于 Pending状态
Pending状态,这个状态意味着,Pod 的 YAML 文件已经提交给 Kubernetes,API 对象已经被创建并保存在 Etcd 当中。但是,这个 Pod 里有些容器因为某种原因而不能被顺利创建。比如,调度不成功(可以通过 kubectl describe pod命令查看到当前 Pod 的事件,进而判断为什么没有调度)。可能原因: 资源不足(集群内所有的 Node 都不满足该 Pod 请求的 CPU、内存、GPU 等资源);HostPort 已被占用(通常推荐使用 Service 对外开放服务端口)。
Pod 一直处于 Waiting或 ContainerCreating状态
首先还是通过 kubectl describe pod命令查看到当前Pod的事件。可能的原因包括:
1、镜像拉取失败比如,镜像地址配置错误、拉取不了国外镜像源(gcr.io)、私有镜像密钥配置错误、镜像太大导致拉取超时(可以适当调整 kubelet 的 --image-pull-progress-deadline 和 --runtime-request-timeout 选项)等。
2、CNI 网络错误,一般需要检查 CNI 网络插件的配置,比如:无法配置 Pod 网络、无法分配 IP 地址。
3、容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数。
4、Failed create pod sandbox,查看kubelet日志,原因可能是磁盘坏道(input/output error)。
Pod 一直处于 ImagePullBackOff状态
通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。这种情况可以使用 docker pull来验证镜像是否可以正常拉取。
如果私有镜像密钥配置错误或者没有配置,按下面检查:
1、查询 docker-registry 类型的 Secret

查看 docker-registry Secret

$ kubectl  get secrets my-secret -o yaml | grep 'dockerconfigjson:' | awk '{print $NF}' | base64 -d

2、创建 docker-registry 类型的 Secret

# 首先创建一个 docker-registry 类型的 Secret
$ kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

# 然后在 Deployment 中引用这个 Secret
spec:
  containers:
  - name: private-reg-container
    image: <your-private-image>
  imagePullSecrets:
  - name: my-secret

Pod 一直处于 CrashLoopBackOff 状态
CrashLoopBackOff 状态说明容器曾经启动了,但又异常退出。此时可以先查看一下容器的日志。
通过命令 kubectl logs 和 kubectl logs --previous 可以发现一些容器退出的原因,比如:容器进程退出、健康检查失败退出、此时如果还未发现线索,还可以到容器内执行命令来进一步查看退出原因(kubectl exec cassandra – cat /var/log/cassandra/system.log),如果还是没有线索,那就需要 SSH 登录该 Pod 所在的 Node 上,查看 Kubelet 或者 Docker 的日志进一步排查。
Pod 处于 Error 状态
通常处于 Error 状态说明 Pod 启动过程中发生了错误。常见的原因包括:依赖的 ConfigMap、Secret 或者 PV 等不存在;请求的资源超过了管理员设置的限制,比如超过了 LimitRange 等;违反集群的安全策略,比如违反了 PodSecurityPolicy 等;容器无权操作集群内的资源,比如开启 RBAC 后,需要为 ServiceAccount 配置角色绑定;
Pod 处于 Terminating 或 Unknown 状态
从 v1.5 开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 Terminating 或 Unknown 状态。想要删除这些状态的 Pod 有三种方法:
***1、从集群中删除该 Node。***使用公有云时,kube-controller-manager 会在 VM 删除后自动删除对应的 Node。而在物理机部署的集群中,需要管理员手动删除 Node(如 kubectl delete node )。
***2、Node 恢复正常。***Kubelet 会重新跟 kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些 Pod。用户强制删除。用户可以执行 kubectl delete pods pod-name --grace-period=0 --force 强制删除 Pod。除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法。特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或者数据丢失等问题。
***3、Pod 行为异常,***这里所说的行为异常是指 Pod 没有按预期的行为执行,比如没有运行 podSpec 里面设置的命令行参数。这一般是 podSpec yaml 文件内容有误,可以尝试使用 --validate 参数重建容器,比如:
kubectl delete pod mypod 和 kubectl create --validate -f mypod.yaml,也可以查看创建后的 podSpec 是否是对的,比如:kubectl get pod mypod -o yaml,修改静态 Pod 的 Manifest 后未自动重建,Kubelet 使用 inotify 机制检测 /etc/kubernetes/manifests 目录(可通过 Kubelet 的 --pod-manifest-path 选项指定)中静态 Pod 的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发生修改静态 Pod 的 Manifest 后未自动创建新 Pod 的情景,此时一个简单的修复方法是重启 Kubelet。
Unknown 这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。