k8s source

kubelet

kubelet 负责以下工作。

  1. 创建、修改和删除 Pod 的容器。
  2. 负责处理活跃度、就绪度和启动探测。
  3. 负责通过读取 pod 配置并在主机上创建相应的目录来挂载卷以进行卷挂载。
  4. 通过调用 API 服务器来收集和报告节点和 Pod 状态。

Kubelet 的 Pod 管理器是 Kubelet 的核心组件之一,它确保节点上的容器和 Pod 处于正确的状态,并与其他组件协同工作,以维护整个集群的稳定性和可用性。 Pod 管理器与 Kubernetes 控制平面交互,以获取 Pod 的期望状态,并负责将节点上的实际状态与期望状态进行协调。这确保了容器应用程序在 Kubernetes 集群中可靠运行

创建pod的过程:

kubectl命令后,进行客户端验证;使用资源对象生成器generaor创建请求;

请求发送到api-server,进行认证鉴权admission controller后,写入etcd;;至此,对象已经在 etcd 中了,所有的初始化步骤也已经完成了。 下一步是设置资源拓扑(resource topology)。例如,一个 Deployment 其实就是一组 ReplicaSet,而一个 ReplicaSet 就是一组 Pod。 K8s 是如何根据一个 HTTP 请求创建出这个层级关系的呢?靠的是 K8s 内置的控制器(controllers)。 以上 controllers 执行完各自的处理之后,etcd 中已经有了一个 Deployment、一个 ReplicaSet 和三个 Pods,可以通过 kube-apiserver 查询到。scheduler 调度器 —— 负责调度到任何节点.到目前为止,我们看到的所有东西(状态),还只是存在于 etcd 中的元数据。 下一步就是将这些状态同步到计算节点上,然后计算节点上的 agent(kubelet)就开始干活了。 通过container runtime与具体的容器运行时交互,创建容器;(grpc实现)

  • ClusterIP (默认) - 在集群的内部 IP 上公开 Service 。这种类型使得 Service 只能从集群内访问。
  • NodePort - 使用 NAT 在集群中每个选定 Node 的相同端口上公开 Service 。使用<NodeIP>:<NodePort> 从集群外部访问 Service。是 ClusterIP 的超集。
  • LoadBalancer - 在当前云中创建一个外部负载均衡器(如果支持的话),并为 Service 分配一个固定的外部IP。是 NodePort 的超集。
  • ExternalName - 通过返回带有该名称的 CNAME 记录,使用任意名称(由 spec 中的externalName指定)公开 Service。不使用代理。这种类型需要kube-dns的v1.7或更高版本。

container runtime

于是,现代 docker 启动一个标准化容器需要经历这样的流程:

  • runc负责容器生命周期管理和与linux内核的交互;;
  • containerd 提供了一个守护进程,用于管理容器的完整生命周期,
  • container shim 作为容器的父进程,将信号向容器进程进行转发,container shim 在 Docker 中的主要作用是在容器的生命周期中保持一个持久的父进程。   ;不让runc作为容器父进程得,允许 containerdrunc 在容器启动后退出,并持续监视容器的生命周期,转发日志和信号,并收集容器的退出状态。

  • k8s CRI shim 的作用就是适配或"转化"具体容器运行时的接口,使其符合 Kubernetes 的 CRI 标准。换句话说,CRI shim 的职责就是作为 Adapter 将各种容器运行时本身的接口适配到 Kubernetes 的 CRI 接口上。

package main

import (
	"fmt"
	"time"
)

func worker(quit chan struct{}) {
	for {
		select {
		case <-quit:  // 接收到退出信号
			fmt.Println("Worker exiting...")
			return  // 退出goroutine
		default:
			fmt.Println("Worker working...")
			time.Sleep(1 * time.Second)  // 模拟工作
		}
	}
}

func main() {
	quit := make(chan struct{})  // 创建一个退出通道

	go worker(quit)  // 启动worker goroutine

	time.Sleep(5 * time.Second)  // 让worker工作一段时间
	close(quit)  // 关闭退出通道,发出退出信号

	time.Sleep(1 * time.Second)  // 等待worker退出
	fmt.Println("Done")
}

package main

import (
	"context"
	"flag"
	"fmt"
	"time"

	"k8s.io/client-go/informers"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	kubeconfig := flag.String("kubeconfig", "/path/to/kubeconfig", "path to kubeconfig file")
	flag.Parse()

	// 创建 Kubernetes 客户端
	config, _ := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	clientset, _ := kubernetes.NewForConfig(config)

	// 创建 Informer 工厂
	informerFactory := informers.NewSharedInformerFactory(clientset, 30*time.Second)

	// 获取 Pod Informer
	podInformer := informerFactory.Core().V1().Pods().Informer()

	// 设置事件处理器
	podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			pod := obj.(*v1.Pod)
			fmt.Printf("Pod Added: %s/%s\n", pod.Namespace, pod.Name)
		},
		DeleteFunc: func(obj interface{}) {
			pod := obj.(*v1.Pod)
			fmt.Printf("Pod Deleted: %s/%s\n", pod.Namespace, pod.Name)
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			newPod := newObj.(*v1.Pod)
			oldPod := oldObj.(*v1.Pod)
			if newPod.ResourceVersion != oldPod.ResourceVersion {
				fmt.Printf("Pod Updated: %s/%s\n", newPod.Namespace, newPod.Name)
			}
		},
	})

	// 启动 Informer
	stopCh := make(chan struct{})
	defer close(stopCh)
	informerFactory.Start(stopCh)

	// 阻塞直到被停止
	<-stopCh
}
  • Informer 工厂: informers.NewSharedInformerFactory 创建一个 Informer 工厂,你可以从中获取特定资源的 Informer。

  • 事件处理器: 使用 AddEventHandlerAddEventHandlerWithResyncPeriod 设置事件处理器,这些处理器在资源发生变化时被调用。

  • 启动 Informer: 使用 informerFactory.Start 启动所有 Informer。它需要一个 stopCh,这个 channel 用于在程序应当停止时关闭所有 Informer。

  • <-stopCh被阻塞知道close(stopCh)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值