1. Docker 是什么?
Docker 是基于容器技术实现的,容器技术最开始是基于 Linux Container(简称 LXC)技术实现的,通过内核提供的 Namespace
和 Cgroup
机制,实现了对应用程序的隔离以及物理资源的分配。
Docker 在容器基础上发展出了一个完善的生态系统,它将容器视为一种打包格式,将应用程序所需的一切,比如依赖库、运行时环境等都集合在了在一起,使得一次构建,到处运行。
它将开发与运维很好的融合在一起。开发人员可以很轻松的构建、打包、推送和运行应用程序。而且还允许我们将容器视为部署单元,以模块化的方式发布,降低了系统的运维管理难度。
2. Docker 基本概念
镜像
镜像就像是包含了操作系统的一张光碟,它是一个模板文件,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
另外,镜像是一个分层的文件系统,通过一层层的组合,使得我们可以复用这些不同粒度的镜像文件。
容器
容器是镜像的运行实例,我们可以把镜像看成是一个个的构建块,容器根据这些构建块搭建起了一个隔离的,拥有整个包的应用程序。每一个容器都是一个标准化单元,确保了在不同机子上也能拥有一致的行为。
数据卷
Docker 对数据持久化的解决方案,数据不会随着容器结束而丢失,通过将宿主机的某一文件目录挂载到容器里来实现。在 Docker 里提供了三种方法来实现目录的挂载:
volumes:
属于 Docker 管理的目录,无需自己创建目录。bind mounts:
自己指定的某个目录,需注意不同操作系统的文件路径格式。tmpfs:
仅存储在主机系统的内存中,不会持久保存在磁盘上。容器可以使用它来共享简单状态或非敏感的信息。
网络
bridge 模式
Docker 在主机上会创建一个 docker0
的网桥,每当有容器要创建时,便会为容器分配一个独立的网卡,然后桥接到虚拟网桥上。这其实是一对虚拟网卡,一端放在容器里,另一端放在 docker0
网桥里。当一端有数据达到时,就会把数据包转发到另一端上,这就实现了网络通信。
host 模式
在建一个容器时,一般会为容器分配一个独立的 Network Namespace 以进行网络隔离。如果我们使用了 Host
模式,则不再分配 Network Namespace,而是和宿主机共用一个 Network Namespace。此时容器将不再拥有自己的虚拟网卡、IP 和端口,而是和宿主机共用一个 IP 和端口。
none 模式
使用 none 模式的容器拥有属于自己的 Network Namespace,但不做任何网络配置。它和宿主机以及其他容器是不互通的。如果需要和外部通信,则需要自定义网络驱动程序,自己添加网卡、配置 IP 等。
3. Docker 的底层技术是什么?
Docker 在 Linux 的底层技术有:Namespaces
(资源隔离)、CGroups
(资源限制)、UnionFS
(联合文件系统)。其中:
- Namespaces(资源隔离):将系统的全局资源通过抽象划分,使得在同一 namespace 中的进程看起来拥有自己的全局资源。主要有 Mount namespaces(文件系统挂载)、Network namespaces(网络)、User namespaces(用户)等的资源隔离。
- CGroups(资源限制):对系统资源的限制,比如 CPU、内存等。
- UnionFS (联合文件系统):一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。便于镜像的分层继承。
4. Docker 和虚拟机的区别?
容器技术和虚拟机都提供了环境隔离的功能。不同的是。容器是运行在操作系统上的一个进程,它和其他应用程序是共享内核的,由操作系统提供虚拟化隔离功能;而虚拟机则是完完全全另起了个操作系统,将环境隔离的更加彻底。
5. Docker 常用命令有哪些?
容器生命周期管理: run、start/stop/restart、kill、rm、pause/unpause
容器操作:ps、inspect、top
镜像仓库:login、pull、push、search
本地镜像管理:images、rmi、tag、build、history
例如,当我们需要运行一个容器时,则可以执行:
docker run nginx:test
6. k8s 是什么,特点?
k8s 是一个容器管理平台,负责容器的编排、管理、调度, 支持故障转移/重启、自动扩缩容、服务发现/负载均衡、配置管理等功能,使得应用服务能从打包到部署再到监控能有一条完整的自动化流程。
7. k8s 相关概念
Container
即容器,通过镜像包含软件的运行环境,加上 namespace 的隔离功能,使得容器可以很方便的在任何地方运行。
Pod
k8s 使用 Pod 来管理容器,一个 Pod 可以包含一个或多个容器。它是一组紧密关联的容器集合,共享 PID、IPC、Network 和 UTS namespace,是 Kubernetes 调度的基本单位。
Pod 内的多个容器共享网络和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。
Node
Node 是 Pod 真正运行的主机,可以是物理机,也可以是虚拟机。为了管理 Pod,每个 Node 节点上至少要运行 container runtime(比如 docker 或者 rkt)、kubelet 和 kube-proxy 服务。
Namespace
Namespace 是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的 pods, services, replication controllers 和 deployments 等都是属于某一个 namespace 的(默认是 default),而 node, persistentVolumes 等则不属于任何 namespace。
Service
Service 是应用服务的抽象,通过 labels 为应用提供负载均衡和服务发现。匹配 labels 的 Pod IP 和端口列表组成 endpoints,由 kube-proxy 负责将服务 IP 负载均衡到这些 endpoints 上。
每个 Service 都会自动分配一个 cluster IP(仅在集群内部可访问的虚拟地址)和 DNS 名,其他容器可以通过该地址或 DNS 来访问服务,而不需要了解后端容器的运行。
Label
Label 是识别 Kubernetes 对象的标签,以 key/value 的方式附加到对象上。Label 不提供唯一性,并且实际上经常是很多对象(如 Pods)都使用相同的 label 来标志具体的应用。
8. k8s 架构图及交互流程
k8s 主要有 Master 节点和工作节点组成。主节点主要对集群做出全局决策(比如调度),以及检测和响应集群事件(例如资源不足,自动扩缩容);从节点负责维护运行的 Pod 并进行通信的网络代理。
Mater 节点主要有以下组件:
- kube-apiserver:负责对外暴露 Kubernetes API。
- etcd:作为保存 Kubernetes 所有集群数据的后台数据库。
- kube-scheduler:在适当的时候进行调度决策,让 Pod 在合适的节点上创建运行。
- kube-controller-manager:负责监控调整调整集群的状态,比如故障检测、自动扩展、滚动更新等
Node 节点有以下组件:
- kubelet:主要负责执行、监控由调度器分配的 Pod,相当于是 Master 在每个 Node 节点上的代理。保证 Pod 的运行状态与目标状态一致。
- kube-proxy:k8s 在每个节点上的网络代理,负责为 Service 提供集群内部的服务发现和负载均衡。
9. k8s 的健康检查机制是什么?
k8s 主要通过提供下面两种探针(probe)来进行 Pod 的健康检测:
- livenessProbe(存活探针):用来确定什么时候要重启容器,例如通过一个 HTTP GET 请求来判断容器是否健康存活。
- readinessProbe(就绪探针):有时候,应用程序会暂时性的不能提供通信服务。(例如启动加载大文件)。在这种情况下,既不想杀死应用程序,也不想给它发送请求。Kubernetes 提供了就绪探测器来发现并缓解这些情况,设置后,流量将不会打到 Service 上。
10. 镜像的下载策略有哪些?
主要分为三种:
- Always:总是从指定的仓库中获取镜像。
- Never:使用本地镜像,不从仓库中下载。
- IfNotPresent:当本地镜像不存在时,才从仓库拉取。
当镜像标签是 latest 时,默认下载策略是 Always。当镜像标签是自定义时,使用 IfNotPresent。
11. Pod 的状态有哪些?
- Pending:pod 正在等待 kube-scheduler 选择合适的节点创建。
- Running:pod 已正常创建,并且至少有一个容器正在运行。
- Succeeded:所有容器已成功启动运行。
- Failed:pod 的容器非正常退出。
- Unknown:无法获取 pod 状态,可能节点间通信出现问题。
12. k8s 创建一个 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 数据中心。
13. 删除 pod 流程
Kube-apiserver 会接受到用户的删除指令,默认有 30 秒时间等待优雅退出,超过 30 秒会被标记为死亡状态,此时 Pod 的状态 Terminating,kubelet 看到 pod 标记为 Terminating 就开始了关闭 Pod 的工作;
14. service 是什么?
Pod 每次重启或者重新部署,其 IP 地址都会产生变化,这使得 pod 间通信和 pod 与外部通信变得困难,这时候,就需要 Service 为 pod 提供一个固定的入口。
Service 的 Endpoint 列表通常绑定了一组相同配置的 pod,通过负载均衡的方式把外界请求分配到多个 pod 上
15. 怎么服务注册?
Pod 启动后会加载当前环境所有 Service 信息,以便不同 Pod 根据 Service 名进行通信。
16. 持久化方式
1)EmptyDir(空目录):没有指定要挂载宿主机上的某个目录,直接由 Pod 内保部映射到宿主机上。类似于 docker 中的 manager volume。
2)Hostpath:将宿主机上已存在的目录或文件挂载到容器内部。类似于 docker 中的 bind mount 挂载方式。
3)PersistentVolume(简称 PV):
基于 NFS 服务的 PV,也可以基于 GFS 的 PV。它的作用是统一数据持久化目录,方便管理。
17. 常用命令
- kubectl create:创建资源(kubectl create -f docker-registry.yaml)
- kubectl run:快速创建容器(kubectl run nginx --image=nginx)
- kubectl get:获取资源列表(kubectl get pods)
- kubectl describe:查看资源详细信息(kubectl describe pods/nginx)
- kubectl exec:在容器内执行命令(kubectl exec podName -c containerName -i -t -- bash -il)
- kubectl logs:查看 pod 日志(kubectl logs nginx)
- kubectl delete:删除一个资源(kubectl delete pods --all)