external-attacher源码分析(1)-main方法与启动参数分析
更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航
摘要
ceph-csi分析-external-attacher源码分析。external-attacher属于external plugin中的一个,辅助csi plugin组件,共同完成了存储相关操作。external-attacher watch volumeAttachment对象,然后调用csi plugin来做attach/dettach操作,并修改volumeAttachment对象与pv对象。
基于tag v2.1.1
https://github.com/kubernetes-csi/external-attacher/releases/tag/v2.1.1
external-attacher
external-attacher属于external plugin中的一个。下面我们先来回顾一下external plugin以及csi系统结构。
external plugin
external plugin包括了external-provisioner、external-attacher、external-resizer、external-snapshotter等,external plugin辅助csi plugin组件,共同完成了存储相关操作。external plugin负责watch pvc、volumeAttachment等对象,然后调用volume plugin来完成存储的相关操作。如external-provisioner watch pvc对象,然后调用csi plugin来创建存储,最后创建pv对象;external-attacher watch volumeAttachment对象,然后调用csi plugin来做attach/dettach操作,并修改volumeAttachment对象与pv对象;external-resizer watch pvc对象,然后调用csi plugin来做存储的扩容操作等。
csi系统结构
external-attacher作用分析
根据CSI plugin是否支持ControllerPublish/ControllerUnpublish操作,external-attacher的作用分为如下两种:
(1)当CSI plugin不支持ControllerPublish/ControllerUnpublish操作时,AD controller(或kubelet的volume manager)创建VolumeAttachment对象后,external-attacher仅参与VolumeAttachment对象的修改,将attached属性值patch为true;而external-attacher对pv对象无任何同步处理操作。
(2)当CSI plugin支持ControllerPublish/ControllerUnpublish操作时,external-attacher调用csi plugin(ControllerPublishVolume)进行存储的attach操作,然后更改VolumeAttachment对象,将attached属性值patch为true,并patch pv对象,增加该external-attacher相关的Finalizer;对于pv对象,external-attacher负责处理pv对象的finalizer,patch pv对象,去除该external-attacher相关的finalizer(该external-attacher执行attach操作时添加的finalizer)。
源码分析
external-attacher的源码分析分为两部分:
(1)main方法以及启动参数分析;
(2)核心处理逻辑分析。
这篇博客先对external-attacher的main方法以及启动参数做分析,下篇博客将对external-attacher的核心处理逻辑进行源码分析。
main
main方法主要逻辑:
(1)解析启动参数;
(2)校验worker-threads配置;
(3)根据配置建立clientset;
(4)建立与csi plugin的grpcclient;
(5)调用csi plugin的探测方法(探测cephcsi-rbd服务是否准备好),直至探测成功;
(6)获取driver名称;
(7)获取csi plugin提供的能力,判断是否提供Controller服务,当不支持时实例化TrivialHandler,当支持时进入下一步;
(8)获取csi plugin提供的能力,判断是否支持ControllerPublish/ControllerUnpublish操作,支持则实例化CSIHandler,不支持则实例化TrivialHandler(CSIHandler与TrivialHandler在下一篇博客再做具体介绍,这里只要知道有这么两个东西就行);
(9)ceph-csi不提供Controller attach服务,所以走NewTrivialHandler;
(10)获取csi plugin提供的能力,判断是否提供ListVolumesPublishedNodes服务;
(11)新建CSIAttachController;
(12)定义run方法,方法中调用CSIAttachController的run方法;
(13)进行高可用选主相关操作,并运行run方法。
func main() {
// 解析启动参数
klog.InitFlags(nil)
flag.Set("logtostderr", "true")
flag.Parse()
// --version输出
if *showVersion {
fmt.Println(os.Args[0], version)
return
}
klog.Infof("Version: %s", version)
// 根据配置建立clientset
// Create the client config. Use kubeconfig if given, otherwise assume in-cluster.
config, err := buildConfig(*kubeconfig)
if err != nil {
klog.Error(err.Error())
os.Exit(1)
}
// 校验worker-threads配置
if *workerThreads == 0 {
klog.Error("option -worker-threads must be greater than zero")
os.Exit(1)
}
// 根据配置建立clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
klog.Error(err.Error())
os.Exit(1)
}
factory := informers.NewSharedInformerFactory(clientset, *resync)
var handler controller.Handler
metricsManager := metrics.NewCSIMetricsManager("" /* driverName */)
// 建立grpcclient
// Connect to CSI.
csiConn, err := connection.Connect(*csiAddress, metricsManager, connection.OnConnectionLoss(connection.ExitOnConnectionLoss()))
if err != nil {
klog.Error(err.Error())
os.Exit(1)
}
// 进行grpc探测(探测cephcsi-rbd服务是否准备好),直至探测成功
err = rpc.ProbeForever(csiConn, *timeout)
if err != nil {
klog.Error(err.Error())
os.Exit(1)
}
// 获取driver名称
// Find driver name.
ctx, cancel := context.WithTimeout(context.Background(), csiTimeout)
defer cancel()
csiAttacher, err := rpc.GetDriverName(ctx, csiConn)
if err != nil {
klog.Error(err.Error())
os.Exit(1)
}
klog.V(2).Infof("CSI driver name: %q", csiAttacher)
metricsManager.SetDriverName(csiAttacher)
metricsManager.StartMetricsEndpoint(*metricsAddress, *metricsPath)
// 获取csi plugin提供的能力,判断是否提供Controller服务
supportsService, err := supportsPluginControllerService(ctx, csiConn)
if err != nil {
klog.Error(err.Error())
os.Exit(1)
}
if !supportsService {
// 实例化TrivialHandler
handler = controller.NewTrivialHandler(clientset)
klog.V(2).Infof("CSI driver does not support Plugin Controller Service, using trivial handler")
} else {
// 获取csi plugin提供的能力,判断是否提供Controller attach服务
// Find out if the driver supports attach/detach.
supportsAttach, supportsReadOnly, err := supportsControllerPublish(ctx, csiConn)
if err != nil {
klog.Error(err.Error())
os.Exit(1)
}
if supportsAttach {
pvLister := factory.Core().V1().PersistentVolumes().Lister()
nodeLister := factory.Core().V1().Nodes().Lister()
vaLister := factory.Storage().V1beta1().VolumeAttachments().Lister()
csiNodeLister := factory.Storage().V1beta1().CSINodes().Lister()
volAttacher := attacher.NewAttacher(csiConn)
CSIVolumeLister := attacher.NewVolumeLister(csiConn)
// 实例化CSIHandler
handler = controller.NewCSIHandler(clientset, csiAttacher, volAttacher, CSIVolumeLister, pvLister, nodeLister, csiNodeLister, vaLister, timeout, supportsReadOnly, csitrans.New())
klog.V(2).Infof("CSI driver supports ControllerPublishUnpublish, using real CSI handler")
} else {
// 实例化TrivialHandler
handler = controller.NewTrivialHandler(clientset)
klog.V(2).Infof("CSI driver does not support ControllerPublishUnpublish, using trivial handler")
}
}
// 获取csi plugin提供的能力,判断是否提供ListVolumesPublishedNodes服务
slvpn, err := supportsListVolumesPublishedNodes(ctx, csiConn)
if err != nil {
klog.Errorf("Failed to check if driver supports ListVolumesPublishedNodes, assuming it does not: %v", err)
}
if slvpn {
klog.V(2).Infof("CSI driver supports list volumes published nodes. Using capability to reconcile volume attachment objects with actual backend state")
}
// 新建CSIAttachController
ctrl := controller.NewCSIAttachController(
clientset,
csiAttacher,
handler,
factory.Storage().V1beta1().VolumeAttachments(),
factory.Core().V1().PersistentVolumes(),
workqueue.NewItemExponentialFailureRateLimiter(*retryIntervalStart, *retryIntervalMax),
workqueue.NewItemExponentialFailureRateLimiter(*retryIntervalStart, *retryIntervalMax),
slvpn,
*reconcileSync,
)
// 定义run方法,方法中调用CSIAttachController的run方法
run := func(ctx context.Context) {
stopCh := ctx.Done()
factory.Start(stopCh)
ctrl.Run(int(*workerThreads), stopCh)
}
// 进行高可用选主相关操作,并运行run方法
if !*enableLeaderElection {
run(context.TODO())
} else {
// Name of config map with leader election lock
lockName := "external-attacher-leader-" + csiAttacher
le := leaderelection.NewLeaderElection(clientset, lockName, run)
if *leaderElectionNamespace != "" {
le.WithNamespace(*leaderElectionNamespace)
}
if err := le.Run(); err != nil {
klog.Fatalf("failed to initialize leader election: %v", err)
}
}
}
启动参数分析
启动参数列表
具体参考https://github.com/kubernetes-csi/external-attacher#command-line-options
// Command line flags
var (
kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig file. Required only when running out of cluster.")
resync = flag.Duration("resync", 10*time.Minute, "Resync interval of the controller.")
csiAddress = flag.String("csi-address", "/run/csi/socket", "Address of the CSI driver socket.")
showVersion = flag.Bool("version", false, "Show version.")
timeout = flag.Duration("timeout", 15*time.Second, "Timeout for waiting for attaching or detaching the volume.")
workerThreads = flag.Uint("worker-threads", 10, "Number of attacher worker threads")
retryIntervalStart = flag.Duration("retry-interval-start", time.Second, "Initial retry interval of failed create volume or deletion. It doubles with each failure, up to retry-interval-max.")
retryIntervalMax = flag.Duration("retry-interval-max", 5*time.Minute, "Maximum retry interval of failed create volume or deletion.")
enableLeaderElection = flag.Bool("leader-election", false, "Enable leader election.")
leaderElectionNamespace = flag.String("leader-election-namespace", "", "Namespace where the leader election resource lives. Defaults to the pod namespace if not set.")
reconcileSync = flag.Duration("reconcile-sync", 1*time.Minute, "Resync interval of the VolumeAttachment reconciler.")
metricsAddress = flag.String("metrics-address", "", "The TCP network address where the prometheus metrics endpoint will listen (example: `:8080`). The default is empty string, which means metrics endpoint is disabled.")
metricsPath = flag.String("metrics-path", "/metrics", "The HTTP path where prometheus metrics will be exposed. Default is `/metrics`.")
)
func main() {
klog.InitFlags(nil)
flag.Set("logtostderr", "true")
flag.Parse()
......
external-attacher容器启动参数
- args:
- --v=5
- --csi-address=$(ADDRESS)
- --leader-election=true
- --retry-interval-start=500ms
env:
- name: ADDRESS
value: /csi/csi-provisioner.sock
volumeMounts:
- mountPath: /csi
name: socket-dir
volumes:
- emptyDir:
medium: Memory
name: socket-dir
下面是部分参数解析:
v
日志打印等级。
csi-address
csi plugin(controller server)暴露服务的socket地址。
leader-election
是否开启高可用选主(使用Leases)。
retry-interval-start
VA/PV对象同步失败后的重试时间间隔。
retry-interval-max
VA/PV对象同步失败后的最大重试时间间隔。
timeout
与CSI driver通信的超时时间,默认15秒。
worker-threads
同步VA/PV对象的工作线程数量,默认10。
总结
external-attacher属于external plugin中的一个。
external-attacher作用分析
根据CSI plugin是否支持ControllerPublish/ControllerUnpublish操作,external-attacher的作用分为如下两种:
(1)当CSI plugin不支持ControllerPublish/ControllerUnpublish操作时,AD controller(或kubelet的volume manager)创建VolumeAttachment对象后,external-attacher仅参与VolumeAttachment对象的修改,将attached属性值patch为true;而external-attacher对pv对象无任何同步处理操作。
(2)当CSI plugin支持ControllerPublish/ControllerUnpublish操作时,external-attacher调用csi plugin(ControllerPublishVolume)进行存储的attach操作,然后更改VolumeAttachment对象,将attached属性值patch为true,并patch pv对象,增加该external-attacher相关的Finalizer;对于pv对象,external-attacher负责处理pv对象的finalizer,patch pv对象,去除该external-attacher相关的finalizer(该external-attacher执行attach操作时添加的finalizer)。
external-attacher与ceph-csi结合使用
ceph-csi不支持ControllerPublish/ControllerUnpublish操作,所以external-attacher与ceph-csi 结合使用,external-attacher仅参与VolumeAttachment对象的修改,将attached属性值patch为true。
external-attacher源码分析(1)-main方法与启动参数分析的更多相关文章
- external-provisioner源码分析(3)-组件启动参数分析
更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 external-provisioner源码分析(3)-组件启动参数分析 本文将对extern ...
- ceph-csi源码分析(2)-组件启动参数分析
更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi源码分析(2)-组件启动参数分析 ceph-csi组件的源码分析分为五部分: ...
- external-provisioner源码分析(2)-main方法与Leader选举分析
更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 external-provisioner源码分析(2)-main方法与Leader选举分析 本 ...
- 如果是多个 c 代码的源码文件,编译方法如下: $ gcc test1.c test2.c -o main.out $ ./main.out test1.c 与 test2.c 是两个源代码文件。
如果是多个 c 代码的源码文件,编译方法如下: $ gcc test1.c test2.c -o main.out $ ./main.out test1.c 与 test2.c 是两个源代码文件.
- spring-boot-2.0.3启动源码篇二 - run方法(一)之SpringApplicationRunListener
前言 Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,争取不让大家每周的期望落空.一周之中可 ...
- 从源码角度看finish()方法的执行流程
1. finish()方法概览 首先我们来看一下finish方法的无参版本的定义: /** * Call this when your activity is done and should be c ...
- Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...
- 51ak带你看MYSQL5.7源码1:main入口函数
从事DBA工作多年 MYSQL源码也是头一次接触 尝试记录下自己看MYSQL5.7源码的历程 目录: 51ak带你看MYSQL5.7源码1:main入口函数 51ak带你看MYSQL5.7源码2:编译 ...
- linux2.4.0源码下载地址(配合毛德操情景分析)
https://www.kernel.org/pub/linux/kernel/v2.4/
随机推荐
- 狄克斯特拉(Dijkstra)算法
引入 从A点到B点的最短路径是什么?求最短路径的两种算法:Dijkstra算法和Floyd算法. 网图:带权图. 非网图最短路径:两顶点间经过的边数最少的路径.(非网图也可被理解为各边权值为1的网图. ...
- [MySQL数据库之Navicat.pymysql模块、视图、触发器、存储过程、函数、流程控制]
[MySQL数据库之Navicat.pymysql模块.视图.触发器.存储过程.函数.流程控制] Navicat Navicat是一套快速.可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降 ...
- [c++] 模板、迭代器、泛型
模板 函数模板:重载的进一步抽象,只需定义一个函数体即可用于所有类型 在C++中,数据的类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的实参自动推 ...
- 小米华为vivooppo手机记录隐私证据查询
1.在拨号界面输入:*#*#4636#*#* 2.在输入代码之后 手机会自动跳转到下面这个页面 就可以查看她到底拿着手机在干嘛 2 输入下面代码可以检测小米手机的各种信息 *#*#64663#*#*
- 【山外笔记-SVN命令】svn命令详解
本文打印版文件下载地址 [山外笔记-SVN命令]svn命令详解-打印版.pdf 一.命令简介 svn命令用于Subversion命令行客户端,执行svn相关的操作. 二.命令语法 1.svn语法: ( ...
- 联想 lenove 3750 M4服务器更改启动项和管理口IP
联想 lenove 3750 M4服务器更改启动项和管理口IP 注: 因为在机房拍照的原因,再加上工作比较忙:整理成文档的时候有的过程已经忘记了,所以有的步骤可能会缺失,里面的选项都已经用中文方式表达 ...
- 如何在我的EC2实例状态更改时获取自定义电子邮件通知
具体详情,请参见: https://amazonaws-china.com/cn/premiumsupport/knowledge-center/ec2-email-instance-state-ch ...
- 003.Python数据类型转换
一 自动类型转换 (针对于Number类型) bool float int complex 当Number不同的数据类型进行运算的时候,默认向更高精度转化 精度从低到高顺序:bool -> in ...
- 微信引流的方式 PC控制手机的方式
http://www.yunjing100.cn/ 云鲸一百 小萝卜 http://www.xiaoluobei.com/
- centos下yum方法安装apache+php+mysql
yum(全称为:Yellow dog Updater,Modified) 是一个在Fedora和RedHat以及SUSE中的Shell前端管理软件.基于RPM包管理,能够从远处镜像服务器下载RPM包并 ...