1. 宿主机如何与容器通信
-
Bridge模式,即使用docker0网桥
默认
- 创建独立的Network Namespace
- 创建容器时会虚拟出网卡创建一对虚拟网卡
veth pair
设备,一端连在容器里(eth0
网卡),另一端接在docker0
网桥 - docker run 通过参数
-p 宿主机端口:容器端口
进行端口映射。本质上是对iptables
做了DNAT
规则,实现端口转发功能,可通过iptables -t nat -vnL
查看 - 同个网桥上的可以直接访问
- 不同网桥上,容器A的流量先通过网桥A到宿主机,再通过网桥B到要访问的容器B
- 优点:隔离性好
- 缺点:相比较Host模式,网络性能略低(多了层路由转发)
-
Host模式,即使用宿主机网络
-net=host
与宿主机共用一个Network Namespace
- 优点:网络性能好
- 缺点:会引入共享网络资源问题,比如端口冲突
-
Container模式
新创建的容器和已有的容器共享一个Network Namespace
,而不是和宿主机共享 -
None模式
会创建Network Namespace,但是不会进行任何网络配置(即没有网卡、路由、ip等信息),需要手动添加
2. pod创建流程
- 客户端提交创建请求,
API Server
的RESTful API
或kubectl
-
API Server
处理用户请求,存储pod数据到etcd -
kube-scheduler
通过API Server watch API
一直监听未绑定的pod,尝试为pod分配主机
- 过滤节点(调度预选):
kube-scheduler
用一组郭泽过滤掉不符合要求的主机。比如说pod制定了所需要的资源量,那可用资源不够的会被过滤掉 - 节点打分(调度优选):对预选的节点进行打分,(考虑一些整体优化策略:pod分散,使用最低负载的节点等)
- 选择节点:选择打分最高的节点,进行binding操作,结果存储到etcd中(调用API Server创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息)
- 目标节点上的
kubelet
通过API Server watch API
定期获取boundpod对象,发现需要创建pod了,则调用Docker API
创建并启动pod -
kubelet
通过CRI(Container Runtime Interface
)获取pod状态,传给API Server,数据被更新到etcd中
3. etcd存储的是什么数据
etcd是一个高可用的分布式键值(key-value)数据库
etcd内部采用raft协议作为一致性算法
etcd至于go实现
服务注册和服务发现
保存了集群所有的网络配置和API Server对象的状态信息
4. 怎么查看etcd数据
exec进到pod,使用etcdctl
命令
$ ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
get / --prefix --keys-only
5. etcd怎么做数据备份和数据恢复
直接备份数据目录(用于单节点)
etcd组件的数据目录默认位于/var/lib/etcd
里使用快照命令备份(可用于集群)
// 备份
$ etcdctl --endpoints=127.0.0.1:2380,ip:port snapshot save backupName.db
// 恢复
$ etcdctl snapshot restore backupName.db --data-dir=/var/lib/etcd
6. pod的状态是怎么监控的,怎么做到改变pod状态的
可能是CRI(Container Runtime Interface
)
7.怎么修改docker容器资源?修改后容器重启吗?那修改pod呢?
// 修改容器不重启
$ docker update -c xxx -m xxx [container_id]
修改pod重启,因为kubelet会去同步etcd的数据syncPod
8. 资源隔离的具体实现
使用Linux的namespace
实现,提供六种隔离机制:
-
UTS
: 主机名与域名 -
IPC
: 信号量、消息队列、共享内存 -
PID
: 进程编号 -
Network
: 网络设备、网络栈、端口等 -
Mount
: 挂载点 -
User
: 用户和用户组
与namespace相关的三个系统调用:
-
clone
创建全新的namespace,由clone创建的新进程就位于这个新的namespace里
创建时传入flags
参数,可选值有CLONE_NEWIPC
、CLONE_NEWNET
、CLONE_NEWNS
、CLONE_NEWPID
、CLONE_NEWUTS
、CLONE_NEWUSER
,分别对应上面六种namespace -
unshare
为已有进程创建新的namespace -
setns
把某个进程放在已有的某个namespace里
9. 资源限制的具体实现
使用Linux的Cgroup
实现,简单说是把进程放到一个组里面统一加以控制。
作用:可以限制、记录、隔离进程组所使用的物理资源(包括:CPU、Memory、IO 等),为容器实现虚拟化提供了基本保证。
原理:将一组进程放在放在一个控制组里,通过给这个控制组分配指定的可用资源,达到控制这一组进程可用资源的目的。
- 资源限制
可以对任务使用的资源总额进行限制,如设定应用运行时使用内存的上限,一旦超过这个配额就发出OOM(Out of Memory)提示 - 优先级分配
通过分配的CPU时间片数量和磁盘IO带宽大小,实际上就相当于控制了任务运行的优先级 - 资源统计
可以统计系统的资源使用,如 CPU 使用时长、内存用量等,这个功能非常适用于计费 - 任务控制
可以对任务执行挂起、恢复等操作
// 可以指定cpu和内存分配大小
$ docker run -c xxx -m xxx image:tag
10. docker现有运行时缺陷
- 基于Linux 64bit,无法在32bit的Linux/Windows/Unix环境下运行
- 网络管理相对简单,主要是基于namespace隔离
- LXC是基于cgroup等linux kernel功能的,因此container的guest系统只能是linux base
- container随着用户进程的停止而销毁,container中的log等用户数据不便收集
- 太依赖namespace
11. k8s资源预留是怎么做的
// 通过该参数
kubelet --system-reserved=memory=4Gi
12. Sandbox作用
sandbox
: 沙盒
是一种安全机制,为运行中的容器提供隔离的环境
13. 自定义k8s controller怎么选主
**etcd锁**
tryLock模式,每次lock都是尝试lock,已被lock就无法锁住,同时也用了租约,过期了自动释放
- 利用租约在etcd集群中创建一个key,这个key有两种形态,存在和不存在,而这两种形态就是互斥量。
- 如果这个key不存在,那么线程创建key,成功则获取到锁,该key就为存在状态。
- 如果该key已经存在,那么线程就不能创建key,则获取锁失败。
14. 二层网络,四层网络,overlay network
-
overlay
为了满足云计算虚拟化的网络能力需求,逐步演化出了Overlay网络技术。
通过虚拟化技术把一个逻辑网络建立在实体网络之上。
在传统二层网络环境下,数据报文是通过查询MAC地址表进行二层转发,而网络设备MAC地址表的容量限制了虚拟机的数量。
常用VXLAN - 二层网络:数据链路层(进行数据的分包)
- 四层网络:传输层(TCP/IP协议在这里)
15. 创建pod怎么实现sidecar注入
使用init-container
配置iptables
规则来做流量劫持转发
16. 怎么查看iptables规则
$ iptables -L
17. Pod terminating时候,ip还在吗,还通吗
ip在,ping不通
18. pause容器的作用,可不可以不要?pause容器的进程树是怎样的?
pause容器作为pod里其他所有容器的parent container,主要有两个职责
- 是pod里其他容器共享Linux namespace的基础
- 扮演PID 1(类似Linux的init进程)的角色,负责处理僵尸进程
进程树由pause容器开始,往下是业务容器
19. docker daemon挂了,容器是什么状态?继续运行还是也挂了?
容器会挂