学了一周的k8s,有一定的进步,问题也不断的增多,为了不让这些问题越拖越多,保证学习进度的情况下,花一天时间对一周所学做一个小总结或者问题解答,以问题为驱动学习。

Flannel和Calico的区别

Flannel 和 Calico 都是容器网络解决方案,但它们之间有以下区别:

数据平面实现方式不同:Flannel 使用虚拟网络(VXLAN)来实现数据平面,而 Calico 则使用路由和 iptables 规则来实现数据平面。

网络拓扑结构不同:Flannel 的网络拓扑结构是扁平的,所有节点都在同一个二层网络中,而 Calico 的网络拓扑结构是层级的,使用BGP 协议实现路由。

支持的平台不同:Flannel 支持多种容器平台,包括 Kubernetes、Docker、Mesos 等,而 Calico 主要针对 Kubernetes。

网络策略实现方式不同:Flannel 的网络策略是通过 iptables 规则实现的,而 Calico的网络策略是通过网络策略对象(Network Policy Object)实现的。

性能表现不同:由于 Flannel 使用 VXLAN 进行封装,会造成额外的 CPU 和网络开销,而 Calico
的路由方式则较为高效,性能表现更好。
综上所述,Flannel 和 Calico 都有各自的优势和适用场景,选择哪个解决方案需要根据具体的需求和环境来决定。

子问题:

BGP协议是什么?

BGP(Border Gateway Protocol,边界网关协议)是一种用于路由选择的自治系统间(AS间)的协议。它是Internet中广泛使用的一种路由协议,也是互联网的骨干协议之一。
BGP协议的主要作用是在自治系统之间交换网络可达性信息,即学习和告知其他自治系统的路由信息。BGP协议可以帮助路由器选择最佳的路径,从而实现互联网的高效路由。它通过路由器之间的TCP连接进行通信,并使用特定的BGP消息交换路由信息。
BGP协议的特点包括: BGP协议是自治系统间的协议,主要用于交换AS级别的路由信息。
BGP协议使用了路径矢量算法,可以选择最短路径和最优路径。 BGP协议可以通过路由策略来控制路由选择,从而提高网络的安全性和稳定性。
BGP协议支持多种路由属性,如AS路径、NEXT_HOP、LOCAL_PREF等,可以更精确地描述路由信息。
BGP协议在互联网中具有重要的作用,它使得网络运营商可以自主选择路由策略,从而实现更高效、更安全、更稳定的路由。同时,BGP协议也存在一些挑战,如路由震荡、路由环路等问题,需要进行一定的优化和管理。



数据平面实现方式,网络策略实现方式都是什么意思?

在 Kubernetes 等容器编排平台中,数据平面是指容器之间的网络通信,而网络策略则是指对容器之间的通信进行限制和控制的功能。
数据平面实现方式指的是容器之间的网络通信是如何实现的。在容器编排平台中,常用的数据平面实现方式包括:
Overlay 网络:使用虚拟网络来实现容器之间的通信,比如 Flannel、Calico、Weave 等等。
Host 网络:使用宿主机的网络来实现容器之间的通信,容器和宿主机之间共享同一个网络命名空间,可以直接进行通信,比如 Docker 默认的 bridge 网络。
其他网络:包括 Macvlan 网络、ipvlan 网络等等。

网络策略实现方式指的是如何实现对容器之间通信的控制和限制。在容器编排平台中,常用的网络策略实现方式包括:
iptables 规则:通过设置iptables 规则来控制容器之间的通信,比如 Flannel。
网络策略对象:通过定义网络策略对象来控制容器之间的通信,比如Calico。
这些实现方式都是为了实现容器之间的网络通信和网络策略控制。不同的实现方式有各自的优缺点和适用场景,需要根据具体情况进行选择和部署。



怎么理解这两句话的,总感觉互相矛盾,怎么理解?

这两句话并不矛盾,Flannel 和 Calico 在数据平面上的实现方式不同,但在网络策略上都是通过 iptables 规则来实现的。
Flannel 使用虚拟网络(VXLAN)来实现数据平面,它会为每个容器创建一个虚拟接口,并将这些接口连接到同一个 VXLAN 网络中。这样,容器之间的通信就会通过 VXLAN 网络进行传输。而 Flannel 的网络策略则是通过 iptables 规则实现的,它会在每个节点上设置 iptables 规则,来控制容器之间的网络通信。这些规则可以基于 IP 地址、端口和协议等条件进行过滤和转发。
Calico 则使用路由和 iptables 规则来实现数据平面。它会为每个容器分配一个唯一的 IP 地址,并使用路由表来进行容器之间的路由。同时,Calico 也会在每个节点上设置 iptables 规则,来控制容器之间的网络通信。不同的是,Calico 的网络策略是通过网络策略对象(Network Policy Object)实现的。网络策略对象可以定义哪些容器可以与哪些容器通信,可以限制流量的方向、端口和协议等条件。
因此,可以理解为 Flannel 和 Calico 在数据平面上的实现方式不同,但它们的网络策略都是通过 iptables 规则来实现的。Flannel 的网络策略是基于 iptables 规则的,而 Calico 的网络策略是通过网络策略对象来控制 iptables 规则的。

Docker有哪些命名空间?K8S呢?

Docker 有以下命名空间:
Mount (mnt) 命名空间:该命名空间隔离文件系统挂载点,每个容器都有自己的挂载点视图,可以挂载不同的文件系统。
UTS (uts) 命名空间:该命名空间隔离主机名和域名。在不同的该命名空间中,可以有不同的主机名和域名。
IPC (ipc) 命名空间:该命名空间隔离进程间通信资源,如消息队列、信号量、共享内存等。
PID (pid) 命名空间:该命名空间隔离进程 ID,每个容器都有自己的进程 ID 空间。
Network (net) 命名空间:该命名空间隔离网络设备、IP 地址端口等网络资源,每个容器都有自己的网络栈,可以有不同的 IP地址、端口等。
User (user) 命名空间:该命名空间隔离用户和用户组 ID,每个容器都有自己的用户和用户组 ID。该命名空间也可以用于提升容器的安全性。
通过使用这些命名空间,Docker 可以实现容器间的隔离,提高容器的安全性和可靠性。

Kubernetes 中有以下几个预定义的命名空间:

default:默认的命名空间,如果没有指定命名空间,会被分配到该命名空间。

kube-system:Kubernetes 系统组件使用的命名空间,例如 kube-dns、kube-proxy、kube-scheduler、kube-controller-manager 等。

kube-public:这是一个特殊的命名空间,用于存储公共的配置信息,可以被所有用户和 Pod 访问。

kube-node-lease:节点租赁控制器使用的命名空间,用于确保每个节点都有一个唯一的租赁 ID。

除了以上预定义的命名空间,用户还可以创建自己的命名空间,用于管理自己的应用程序和服务。在 Kubernetes 中,命名空间是一种逻辑隔离机制,可以将不同的资源对象分组和隔离,从而避免资源冲突和混乱。在同一个命名空间中,所有的资源对象都具有相同的名称,可以通过它们的名称进行引用和访问。

pod有哪些状态?

Pod 有以下几种状态:

Pending(等待中):Pod 已经被创建,但是容器镜像还没有被拉取到节点上,或者某些容器正在等待其他容器完成初始化。

Running(运行中):Pod 中的所有容器都已经被创建并且至少有一个容器处于运行状态。

Succeeded(已成功):Pod 中的所有容器都已经成功地完成了任务并且已经退出。这种状态通常是用于执行一次性任务的 Pod。

Failed(已失败):Pod 中的所有容器都已经退出,并且至少有一个容器因为错误而退出。

Unknown(未知):Kubernetes 无法获取 Pod 的状态,这种情况通常是由于与 API 服务器的通信故障导致的。
除了以上状态,Pod 还可以有一些临时状态,例如:

ContainerCreating(正在创建容器):Pod 中的某个容器正在被创建。

ContainerRunning(容器运行中):Pod 中的某个容器正在运行。

ContainerTerminated(容器终止):Pod 中的某个容器已经终止。
总之,Pod 可能会处于多种状态,这些状态可以反映出 Pod 的健康状况和容器的运行情况,通过监控和管理这些状态,可以保证应用程序的稳定运行。

面试官让我讲一下kubernetes的详细流程

Kubernetes 是一个用于容器编排和管理的平台,它的工作流程通常可以分为以下几个步骤:

创建集群:在 Kubernetes 中,首先需要创建一个集群,包括几个节点和一个控制平面(包括 API 服务器、调度程序、控制器管理器和etcd 存储等组件)。

定义 Pod 和容器:在 Kubernetes 中,应用程序通常被定义为一个或多个 Pod,每个 Pod 包含一个或多个容器。Pod可以使用 YAML 文件进行定义,其中包括容器镜像、端口、存储卷以及容器之间的关系等信息。

调度 Pod 和容器:在 Kubernetes 中,使用调度程序将 Pod 调度到可用的节点上。调度程序根据节点的资源和 Pod 的需求来选择最佳的节点。一旦 Pod 被调度到节点上,Kubernetes 就会创建容器并启动应用程序。

监控和管理:Kubernetes 提供了丰富的监控和管理工具,可以监控和管理 Pod 和容器的状态、资源使用情况、日志输出等信息,以确保应用程序的稳定运行。

伸缩和升级:Kubernetes 提供了伸缩和升级的功能,可以根据应用程序的需求动态地调整 Pod 和容器数量,以确保应用程序的高可用性和性能。

清理和删除:在 Kubernetes 中,可以随时清理和删除不需要的 Pod 和容器,以释放资源并保持集群的整洁。
总之,Kubernetes 提供了一种高效、可靠、可扩展的容器编排和管理平台,可以帮助开发人员和运维人员轻松地管理和部署应用程序。

面试官让你讲解pod的启动流程

Pod 是 Kubernetes 中最小的可部署单元,通常包含一个或多个容器。Pod 的启动流程通常可以分为以下几个步骤:

创建 Pod:通过 Kubernetes API 或命令行工具创建 Pod 对象,并指定 Pod 的名称、标签、容器等信息。

Pod 调度:Kubernetes 调度器会将 Pod 调度到集群中的某个节点上。调度器会考虑节点的资源、标签、Pod 的需求等因素,选择最合适的节点。

创建容器:一旦 Pod 被调度到节点上,Kubernetes 就会创建容器并启动应用程序。如果 Pod 包含多个容器,则会依次创建每个容器。

Pod 生命周期:Pod 有三种生命周期阶段,分别是 Pending、Running 和 Succeeded/Failed。在 Pending 阶段,Kubernetes 正在为 Pod 分配资源。在 Running 阶段,Pod 中的容器正在运行。在 Succeeded/Failed 阶段,Pod 中的所有容器已经完成或失败。

容器状态:在 Pod 运行期间,Kubernetes 会监控容器的状态,例如容器的运行状态、资源使用情况、日志输出等信息。如果容器出现故障或崩溃,Kubernetes 会自动重启容器。

Pod 清理:当一个 Pod 不再需要时,Kubernetes 会自动清理 Pod 对象及其关联的资源,例如容器、存储卷等。
总之,Pod 的启动流程是一个复杂的过程,涉及到 Pod 的创建、调度、容器创建、生命周期管理、容器状态监控和清理等多个方面。Kubernetes 提供了丰富的工具和功能,可以帮助用户轻松地管理和部署 Pod,提高应用程序的可用性和稳定性。

k8s有哪些重要的控制器

在 Kubernetes 中,控制器是一种管理 Pod 和其他 Kubernetes 对象的机制。Kubernetes 中的控制器通常包括以下几种:

ReplicaSet 控制器:ReplicaSet 控制器用于管理 Pod 的副本数量。它会在 Pod 发生故障或需要扩展时自动创建或销毁 Pod 的副本,以确保指定的副本数始终处于运行状态。

Deployment 控制器:Deployment 控制器是一种高级的 ReplicaSet 控制器,它可以管理 Pod
的多个版本,并支持滚动升级和回滚操作。Deployment 控制器可以帮助用户实现无宕机升级和回滚操作,提高应用程序的可用性和稳定性。

StatefulSet 控制器:StatefulSet 控制器用于管理有状态应用程序,例如数据库或缓存。它可以确保每个 Pod 在重启或故障恢复后都具有相同的身份和状态,以确保应用程序的一致性和可用性。

DaemonSet 控制器:DaemonSet 控制器用于在每个节点上运行一个 Pod,通常用于运行一些系统级别的服务,如日志收集器或监控代理。DaemonSet 控制器可以确保每个节点上都运行了指定的 Pod。

Job 控制器:Job 控制器用于一次性任务,例如批处理作业或数据处理任务。Job 控制器可以确保任务在容器中运行,直到任务完成为止,并支持任务的重试和并行执行。

CronJob 控制器:CronJob 控制器用于定时任务,例如备份和清理任务。它可以定期创建 Job 对象来执行指定的任务。
以上控制器是Kubernetes 中的一些重要的控制器,它们可以帮助用户自动管理和扩展 Kubernetes 中的各种对象,提高应用程序的可用性和稳定性。

子问题:

常见的 Kubernetes 对象

在 Kubernetes 中,有许多不同类型的对象,每种对象都有其特定的用途和行为。 Pod(容器组):是 Kubernetes
中最小的可部署单元,它可以包含一个或多个容器。 ReplicaSet(副本集):用于确保指定数量的 Pod
副本正在运行,并在其中一个失败时自动替换它。 Deployment(部署):用于创建和更新
ReplicaSet,确保应用程序以期望的方式运行。 Service(服务):用于将一个或多个 Pod 暴露给集群内或集群外的其他服务使用。
ConfigMap(配置映射):用于存储应用程序的配置数据。 Secret(秘密):用于存储敏感数据,如密码、密钥等。
Namespace(命名空间):用于将集群划分成多个虚拟集群,以便不同团队或应用程序可以独立管理。 Node(节点):是
Kubernetes 集群中的一个工作节点,可以运行一个或多个 Pod。 Volume(卷):用于在容器之间共享数据。
PersistentVolume(持久卷):用于将持久化存储资源暴露给 Pod。
PersistentVolumeClaim(持久卷声明):用于请求持久卷资源。
StatefulSet(有状态集):用于部署有状态的应用程序,如数据库等。 DaemonSet(守护进程集):用于在每个节点上运行一个
Pod 的副本,用于系统级的后台任务。 Job(任务):用于运行一次性的任务,如数据迁移、批处理等。
CronJob(定时任务):用于定期运行任务。

这些对象组合在一起,可以构建出复杂的分布式应用程序。



这么多的控制器,它们的启动顺序是怎么样的?

在 Kubernetes 中,各种控制器的启动顺序通常是由 Kubernetes Master 组件的启动顺序决定的。Kubernetes Master 组件包括 kube-apiserver、kube-scheduler、kube-controller-manager、etcd 等组件,它们之间的启动顺序通常是依次启动,逐个启动完成后才能启动控制器。
具体来说,Kubernetes Master 组件的启动顺序通常如下:
启动 etcd:etcd 是 Kubernetes 数据存储的后端,必须先启动 etcd,以保证后续组件的正常工作。

启动 kube-apiserver:kube-apiserver 是 Kubernetes 的 API Server,是集群中各组件之间通信的核心,必须在 etcd 启动后才能启动。

启动 kube-scheduler:kube-scheduler 是 Kubernetes 的调度器,负责将 Pod 调度到集群中的某个节点上,必须在 kube-apiserver 启动后才能启动。

启动 kube-controller-manager:kube-controller-manager 是 Kubernetes 的控制器管理器,包括多个控制器,如 ReplicationController、Deployment、Service 等,必须在 kube-apiserver 启动后才能启动。

启动 kubelet 和 kube-proxy:kubelet 是 Kubernetes 集群中每个节点上的代理程序,负责管理节点上的Pod;kube-proxy 是 Kubernetes 集群中的网络代理,负责实现 Pod 的网络访问策略,必须在 etcd、kube-apiserver、kube-scheduler、kube-controller-manager 启动后才能启动。
总之,控制器的启动顺序与 Kubernetes Master 组件的启动顺序密切相关,必须保证 Kubernetes Master
组件全部启动完成后才能启动控制器,以确保集群的正常运行。



在这里插入图片描述

kubelet是定期主动访问api server知道有哪些pod需要启动,还是scheduler主动去通知kubelet去访问api server的?

kubelet 是 Kubernetes 集群中每个节点上的代理程序,负责管理节点上的 Pod。kubelet 会定期向 Kubernetes API Server 发送请求,获取 Pod 的最新状态,并根据需要创建、删除或更新 Pod。因此,kubelet 是定期主动访问 API Server 知道有哪些 Pod 需要启动。
Scheduler 是 Kubernetes 集群中的另一个重要组件,它负责将 Pod 调度到集群中的某个节点上,并为每个 Pod 分配资源。Scheduler 不会直接通知 kubelet 去访问 API Server,而是将 Pod 的调度信息写入 API Server 中,并由 kubelet 定期获取更新。这样可以保证 kubelet 在任何时候都能获取到最新的 Pod 调度信息,并根据需要创建、删除或更新 Pod。
因此,kubelet 是通过定期访问 API Server 来获取 Pod 最新状态的,而 Scheduler 不会直接通知 kubelet 去访问 API Server。这种设计可以确保集群中的各个组件之间的协作和一致性,同时提高整个集群的可用性和稳定性。

etcd数据发生了变化,哪些控制器是如何知道的?是其他程序通知的还是,定时去检查的?

在 Kubernetes 集群中,etcd 是 Kubernetes 数据存储的后端,存储了 Kubernetes 的所有配置信息和集群状态信息。当 etcd 中的数据发生变化时,Kubernetes 中的各个控制器需要及时获取新的信息,以便及时更新和调整集群状态。
在 Kubernetes 中,控制器通常是以 Pod 的形式运行在集群中的,并通过 Kubernetes API Server 与 etcd 进行交互。当 etcd 中的数据发生变化时,Kubernetes API Server 会将变化的信息推送给相关的控制器,控制器再根据需要进行相应的操作。这种方式可以保证控制器及时获取最新的信息,并采取相应的措施来保证集群的稳定性和可用性。
此外,Kubernetes 中的一些控制器也会定期检查 etcd 中的数据是否发生变化,以确保控制器始终处于最新状态。例如,Deployment 控制器会定期检查 etcd 中的 Deployment 对象是否发生变化,以便及时更新 Pod 的副本数,保证应用程序的可用性。
综上所述,当 etcd 中的数据发生变化时,Kubernetes 中的控制器通常是通过 Kubernetes API Server 接收到变化的信息,并根据需要采取相应的措施来保证集群的稳定性和可用性。部分控制器也会定期检查 etcd 中的数据是否发生变化,以确保始终处于最新状态。

子问题:

Deployment 控制器和 Deployment 对象 区分不清?

Deployment 控制器和 Deployment 对象是 Kubernetes 中的两个不同的概念。
Deployment 控制器是 Kubernetes 系统中的一个控制器对象,它负责管理 Deployment 对象的生命周期。Deployment 控制器会根据 Deployment 对象的定义,创建并维护一组 Pod 副本,确保它们按照所定义的副本数在集群中运行。如果某一个 Pod 副本出现故障,Deployment 控制器会自动将其替换,以保证整个 Deployment 仍然满足所定义的副本数。Deployment 控制器还支持滚动更新(Rolling Update)和回滚(Rollback)等功能,可以实现无宕机的应用程序更新。
Deployment 对象则是 Kubernetes 中的一种资源对象,它定义了一个应用程序的部署策略,包括需要运行的容器镜像、容器数量、容器的资源限制、升级策略等信息。Deployment 对象的定义通常包括一个或多个容器的 Pod 模板(Pod Template),用于创建和管理一组 Pod 副本。Deployment 对象的定义会被提交给 Kubernetes API Server,并由 Deployment 控制器进行解析和执行。
因此,Deployment 控制器是 Kubernetes 中的一个控制器对象,用于管理 Deployment 对象的生命周期;而 Deployment 对象则是 Kubernetes 中的一种资源对象,用于定义应用程序的部署策略。

Docker里实现跨宿主机通信,K8S呢?

在 Docker 中,容器与容器之间默认是隔离的,无法直接进行通信。但是,我们可以通过一些方法实现跨宿主机的容器间通信,包括以下几种方式:

1.使用 Docker 网络
Docker 提供了一种网络模型,可以创建自定义网络并将容器连接到该网络中。在同一个网络中的容器可以相互通信,无论它们位于哪个宿主机上。具体的操作步骤如下:
1)创建一个自定义网络

docker network create mynetwork

2)启动容器并将其连接到该网络

docker run -d --name container1 --network mynetwork image1
docker run -d --name container2 --network mynetwork image2

这样,container1 和 container2 就可以相互通信了。

2. 使用容器代理
我们可以在同一个宿主机上启动一个容器代理,然后将需要通信的容器连接到该代理容器中。代理容器负责转发数据包,从而实现跨宿主机的容器间通信。具体的操作步骤如下:
1)启动容器代理

docker run -d --name proxy image1

2)将需要通信的容器连接到代理容器中

docker run -d --name container1 --link proxy:image1 --env PROXY_PORT=80 image2
docker run -d --name container2 --link proxy:image1 --env PROXY_PORT=80 image3

这样,container1 和 container2 就可以通过代理容器实现通信了。

3. 使用主机网络
我们可以选择使用主机网络模式启动容器,这样容器就可以直接使用主机的网络栈,从而实现跨宿主机的容器间通信。具体的操作步骤如下:
1)启动容器并使用主机网络模式

docker run -d --name container1 --network host image1
docker run -d --name container2 --network host image2

这样,container1 和 container2 就可以直接通信了。

总之,在 Docker 中实现跨宿主机的容器间通信需要使用一些特殊的技术手段,如 Docker 网络、容器代理、主机网络等。我们可以根据具体的需求选择合适的方法,从而实现容器间的通信。


在 Kubernetes 集群中,可以通过多种方式实现跨宿主机通信,下面介绍其中常用的几种方式:
使用 Kubernetes 的内置 Overlay 网络:Kubernetes 内置了多种 Overlay 网络插件,比如 Flannel、Calico 等,可以在不同宿主机之间建立虚拟网络,用于容器之间的通信。在使用 Overlay 网络时,每个宿主机上都会运行一个网络代理程序(flanneld、calico-node 等),用于管理虚拟网络的创建、维护和拆除。

使用 Host 网络:在 Host 网络模式下,容器直接使用宿主机的网络命名空间,可以直接访问宿主机的 IP 地址和端口。在这种模式下,容器之间的通信不需要通过网络代理,因此具有较低的延迟和较高的带宽。

使用 NodePort:NodePort 是 Kubernetes 中的一种服务类型,可以将一个 Pod 暴露给集群外部的网络。当使用 NodePort 时,Kubernetes 会为该服务分配一个随机端口,并将该端口映射到集群中每个工作节点的 IP 地址上。这样,外部网络就可以通过任意一个节点的 IP 地址和端口来访问该服务。

使用 LoadBalancer:LoadBalancer 也是 Kubernetes 中的一种服务类型,可以将一个 Pod 暴露给外部网络,并通过负载均衡器来分发流量。当使用 LoadBalancer 时,Kubernetes 会自动为该服务创建一个负载均衡器,并将其配置为将流量分发到该服务的 Pod 上。

使用 Ingress:Ingress 是 Kubernetes 中的一种 API 对象,用于将多个服务暴露给外部网络,并通过一个统一的入口点来管理这些服务。当使用 Ingress 时,可以配置不同的路由规则,将请求分发到不同的服务上,从而实现跨宿主机的通信。

需要注意的是,使用这些方式进行跨宿主机通信时,需要确保网络安全和访问控制。可以使用 Kubernetes 中的网络策略对象、安全组、防火墙等工具来限制不必要的网络访问,并保护应用程序的安全。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐