Pod
Pod的组成 ?
每个Pod都有一个Pause容器和多个业务容器。
多个业务容器共享Pause容器的IP和Volume。
属于同一个Pod的容器仅通过localhost就可以通信。
Pod的生命周期有哪几种?
五种。Pending、Running、Succeeded、Failed、Unknown。
Pod的探针有哪几种?
两种。
- LivenessProbe:判断容器是否Running。如果不存活,kubelet将杀掉该容器,并根据重启策略进行处理。
- ReadinessProbe:判断容器是否Ready,达到Ready状态的Pod才能接收请求。
Pod的怎么检测容器健康状态?
可通过三种方式实现。
- ExecAction:在容器内部执行命令,返回为0则说明状态蒸菜。
- TCPSocketAction:通过容器IP地址和端口执行TCP检查,能建立TCP连接说明容器健康。
- HTTPGetAction:对容器IP地址、端口和路径调用HTTP Get方法,返回200-400说明健康。
Pod如何滚动升级?
第一种方法:直接再Deployment定义中,通过spec.strategy指定Pod更新的策略,有两种:
- Recreate:先杀掉所有正在运行的pod,再创建新的Pod。
- RollingUpdate:以滚动更新的方式逐个更新Pod。配合maxUnavailable(不可用Pod的上限)和maxSurge(超过期望副本的上限)来控制。
对于滚动升级,更新Deployment时,创建一个新的ReplicaSet,将副本控制为1,然后将旧的ReplicaSet副本减一,再逐个调整,直到更新完。
第二种:使用kubectl rolling-update
命令做滚动升级。
滚动升级通过执行kubectl rolling-update命令一键完成,该命令创建了一个新的RC,然后自动控制旧的RC中的Pod副本数量逐渐减少到0,同时新的RC中的Pod副本的数量从0逐步增加到目标值,最终实现了Pod的升级。
Pod如何回滚?
使用kubectl rollout history
命令检查部署历史记录;
使用kubectl rollout pause
命令暂停Deployment更新操作;
修改信息
使用kubectl rollout resume deploy
命令恢复部署操作;
使用kubectl rollout undo deployment nginx-deployment --to-revision=5
命令回退到指定版本。
从集群外部怎么访问Pod?
- hostPort:某个容器端口映射到物理机上。使用物理机IP+hostPort访问某个容器。
- hostNetwork:true:Pod所有容器都映射到物理机上。
Endpoint是什么?
Endpoint=Pod IP + containerPort
StatefulSet
StatefulSet适用场景?
有状态的服务,比如zk集群,mysql集群等等。他们的特点是:
- 每个节点有固定ID。
- 集群的规模固定。
- 每个节点都是有状态的,会持久化数据到永久存储中。
- 磁盘不能损坏,否则不能提供服务。
StatefulSet的特征 ?
- 每个Pod都有唯一稳定的网络标识符;(每一个Pod实例都有一个唯一的DNS域名,可以直接访问)
- Pod副本的启停是受控的,操作第n个Pod时,前n-1的Pod都是ready的;
- Pod采用稳定的持久化存储卷PV+PVC,删除Pod不会删除相关的存储卷;
Headless Service和普通的Service有什么不同?
Headless Service没有Cluster IP,解析DNS域名是返回的是所有Pod的Endpoint列表。
Service
Service到后端Pod有哪些LB策略?
两种。
- RoundRobin(默认):轮询转到后端Pod。
- SessionAffinity:基于客户端IP的会话保持,相同客户端会到相同Pod。
怎么做服务发现?
每个Service都配置了一个全局唯一的Cluster IP和名称 ,在Service整个生命周期内,ClusterIP不发生改变。
因此,服务发现可以用Service的Name和Cluster IP地址做DNS域名映射。
DNS服务是怎么做的?
使用CoreDNS,使用不同的插件来增强kube-dns中的功能。
- 修改每个Node上kubelet启动参数并重启kubelet;
- 创建CoreDNS应用
- ConfigMap:设置CoreDNS主配置文件Corefile内容
- Deployment:设置CoreDNS容器应用的内容
- Service:DNS服务的配置,设置固定ClusterIP
外部系统怎么访问Service?
由于ClusterIP是一个虚拟IP,只能在集群内部访问,不能对外暴露。因此,可以采用NodePort方式,在集群的每个Node都为需要外部访问的Service开启一个对应的TCP监听端口,外部系统只要用任意一个Node的IP地址+NodePort端口号就可以访问服务。
ConfigMap
ConfigMap想要解决的问题?
配置文件中的参数在容器运行时如何修改。 Docker提供通过Docker Volume将容器外的配置文件映射到容器内的方式,但需要首先把配置文件拷贝到主机上,在分布式环境下要做到文件一致性比较复杂。
ConfigMap的解法
- 定义ConfigMap资源对象,在data域中声明k-v对的配置项,将整个Map持久化到Etcd中。
- 将存储在Etcd中的ConfigMap通过Volume映射的方式挂载到目标Pod内。无论Pod调度到那台node上,都完成自动映射。
- 在Pod使用时,可以通过环境变量(env)或者volumes来使用。
env:
- name:APPLOGLEVEL
valueFrom:
configMapKeyRef:
name: cm-appvars
key: apploglevel
volumes:
- name:serverxml
configMap
name: cm-appconfigfiles
items:
-key: key-serverxml
path:server.xml
ConfigMap是否一定能热更新?
使用ConfigMap并不是每次都可以热更新的,总结下来:
1) 在环境变量或Init-container中使用ConfigMap不能热更新。因为ENV 是在容器启动的时候注入的,启动之后 kubernetes 就不会再改变环境变量的值。同理,init-containeer也只会运行一次。
2) ConfigMap作为Volume进行挂载时可以热更新,但有延迟。更新操作由 kubelet 的 Pod 同步循环触发。每次进行 Pod 同步时(默认每 10 秒一次),Kubelet 都会将 Pod 的所有 ConfigMap volume 标记为"需要重新挂载(RequireRemount)",而 kubelet 中的 volume 控制循环会发现这些需要重新挂载的 volume,去执行一次挂载操作。在 ConfigMap 的重新挂载过程中,kubelet 会先比较远端的 ConfigMap 与 volume 中的 ConfigMap 是否一致,再做更新。要注意,"拿远端的 ConfigMap" 这个操作可能是有缓存的,因此拿到的并不一定是最新版本。
3)使用subPath将ConfigMap文件挂载到其他目录,无法热更新。
ConfigMap怎么热更新和Pod滚动升级?
- 针对可以热更新的场景(Volume挂载),进行配置热更新。
如果有实时性要求,就在应用内监听本地文件的变化,在文件变更时触发一次配置热升级。如果没有实时性要求,就使用configMap本身的更新逻辑。 - 对于不能热更新的场景(使用env, init-container, subPath),滚动更新Pod。
方法一:使用controller来监听ConfigMap变更触发滚动升级。
方法二:修改pod annotation强制触发滚动升级,比如说添加version/config,修改这个值来触发滚动升级;或者直接把configmap转化为json放到pod模板里。
API Server
Kubernetes API Server的核心功能是什么?
提供k8s各类资源对象的增删改查Watch等REST接口。它通过运行在Master上的kube-apiserver进程提供服务。
Kubernetes API Server的架构是什么样的?
四层。
- API层:以REST方式提供各种接口
- 访问控制层:鉴权、验证身份等
- 注册表层:资源对象保存在注册表中
- edcd数据库
List-watch机制提供了什么功能?
- etcd提供了watch接口,API sever可以watch在etcd上发生的数据操作;
- API server模仿etcd的watch API提供了自己的watch接口,K8S的其他组件可以在API server上监听自己感兴趣的资源;
- 可以实现数据同步。客户端调用API Server的List接口将数据缓存在本地(HTTP短链接),然后启动对应资源的watch协程,在收到watch事件后,对内存中的全量资源做同步修改(HTTP长连接)。
Watch是怎样实现的?
使用分块传输编码。
当客户端调用Watch API时, API server在response的HTTP header中设置Transfer-Encoding为chunked,客户端收到消息后,和服务端复用这个连接,等待下一个数据块。
K8S如何保证消息可靠性、实时性和顺序性?
K8S关注消息的最终一致性。
- 可靠性:list和watch保证。List查询当前资源状态,客户端可以比较期望状态和当前状态,纠正不一致的资源。
- 实时性:每当API Server资源产生状态变更事件,都会将事件及时推送给客户端。
- 顺序性:K8S在每个资源事件中都带上了递增的resourceVersion标签,当客户端并发处理同一个资源的事件,就可以比较resourceVersion保证最终状态一致。
- 高性能:watch使用分块传输方式复用一条长连接。
K8S集群中各模块怎么通信?
API Server作为集群的核心,负责各模块的通信。集群内各模块通过API server把信息存入etcd,需要操作时,通过REST接口实现模块的信息交互。
Kubelet与API Server:1)每个Node上的Kubelet每隔一定周期,调用一次API Server接口报告自身状态。API Server将状态更新到etcd。2)Kubelet通过API server接口watch Pod信息,如果Pod绑定在本node,就执行相应容器创建和初始化工作;如果Pod被删除/更新,就执行本节点的Pod删除/更新。
kube-scheduler-manager与API Server:通过API server的Watch接口监听到新建Pod信息后,检索所有符合要求的Node,执行Pod调度机制,将Pod绑定在node上。
Scheduler
Scheduler的作用是什么?
将待调度的Pod按照特定的调度算法和调度策略绑定到集群中某个合适的node上,并将绑定信息写到etcd。
Scheduler的调度流程是什么?
分为两步。
- 预选调度:遍历所有目标Node,根据预选策略,筛选出符合要求的候选节点。
- 确定最优节点:采用优选策略计算每个候选节点的积分,积分最高者胜出。