欢迎关注我的公众号:

目前刚开始写一个月,一共写了18篇原创文章,文章目录如下:

istio多集群探秘,部署了50次多集群后我得出的结论

istio多集群链路追踪,附实操视频

istio防故障利器,你知道几个,istio新手不要读,太难!

istio业务权限控制,原来可以这么玩

istio实现非侵入压缩,微服务之间如何实现压缩

不懂envoyfilter也敢说精通istio系列-http-rbac-不要只会用AuthorizationPolicy配置权限

不懂envoyfilter也敢说精通istio系列-02-http-corsFilter-不要只会vs

不懂envoyfilter也敢说精通istio系列-03-http-csrf filter-再也不用再代码里写csrf逻辑了

不懂envoyfilter也敢说精通istio系列http-jwt_authn-不要只会RequestAuthorization

不懂envoyfilter也敢说精通istio系列-05-fault-filter-故障注入不止是vs

不懂envoyfilter也敢说精通istio系列-06-http-match-配置路由不只是vs

不懂envoyfilter也敢说精通istio系列-07-负载均衡配置不止是dr

不懂envoyfilter也敢说精通istio系列-08-连接池和断路器

不懂envoyfilter也敢说精通istio系列-09-http-route filter

不懂envoyfilter也敢说精通istio系列-network filter-redis proxy

不懂envoyfilter也敢说精通istio系列-network filter-HttpConnectionManager

不懂envoyfilter也敢说精通istio系列-ratelimit-istio ratelimit完全手册

————————————————

加微信群请联系:

type DrainCmdOptions struct {//drain结构体PrintFlags *genericclioptions.PrintFlagsToPrinter  func(string) (printers.ResourcePrinterFunc, error)Namespace stringdrainer   *drain.HelpernodeInfos []*resource.Infogenericclioptions.IOStreams
}
func NewDrainCmdOptions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *DrainCmdOptions {o := &DrainCmdOptions{//初始化drain结构体PrintFlags: genericclioptions.NewPrintFlags("drained").WithTypeSetter(scheme.Scheme),IOStreams:  ioStreams,drainer: &drain.Helper{GracePeriodSeconds: -1,Out:                ioStreams.Out,ErrOut:             ioStreams.ErrOut,},}o.drainer.OnPodDeletedOrEvicted = o.onPodDeletedOrEvictedreturn o
}
//创建drain命令
func NewCmdDrain(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {o := NewDrainCmdOptions(f, ioStreams)//初始化结构体cmd := &cobra.Command{//创建cobra命令Use:                   "drain NODE",DisableFlagsInUseLine: true,Short:                 i18n.T("Drain node in preparation for maintenance"),Long:                  drainLong,Example:               drainExample,Run: func(cmd *cobra.Command, args []string) {cmdutil.CheckErr(o.Complete(f, cmd, args))//准备cmdutil.CheckErr(o.RunDrain())//运行},}cmd.Flags().BoolVar(&o.drainer.Force, "force", o.drainer.Force, "Continue even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet.")//force选项cmd.Flags().BoolVar(&o.drainer.IgnoreAllDaemonSets, "ignore-daemonsets", o.drainer.IgnoreAllDaemonSets, "Ignore DaemonSet-managed pods.")//ignore-daemonsets选项cmd.Flags().BoolVar(&o.drainer.DeleteLocalData, "delete-local-data", o.drainer.DeleteLocalData, "Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained).")//delete-local-data选项cmd.Flags().IntVar(&o.drainer.GracePeriodSeconds, "grace-period", o.drainer.GracePeriodSeconds, "Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.")//grace-period选项cmd.Flags().DurationVar(&o.drainer.Timeout, "timeout", o.drainer.Timeout, "The length of time to wait before giving up, zero means infinite") //timeout选项cmd.Flags().StringVarP(&o.drainer.Selector, "selector", "l", o.drainer.Selector, "Selector (label query) to filter on")//selector选项cmd.Flags().StringVarP(&o.drainer.PodSelector, "pod-selector", "", o.drainer.PodSelector, "Label selector to filter pods on the node")//pod-selector选项cmdutil.AddDryRunFlag(cmd)//干跑选项return cmd
}
//准备方法
func (o *DrainCmdOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {var err errorif len(args) == 0 && !cmd.Flags().Changed("selector") {//args和selector不能同时不指定return cmdutil.UsageErrorf(cmd, fmt.Sprintf("USAGE: %s [flags]", cmd.Use))}if len(args) > 0 && len(o.drainer.Selector) > 0 {//args和selector不能同时指定return cmdutil.UsageErrorf(cmd, "error: cannot specify both a node name and a --selector option")}o.drainer.DryRun = cmdutil.GetDryRunFlag(cmd)//设置干跑if o.drainer.Client, err = f.KubernetesClientSet(); err != nil {//设置clientsetreturn err}if len(o.drainer.PodSelector) > 0 {//如果指定了pod-selector,解析if _, err := labels.Parse(o.drainer.PodSelector); err != nil {return errors.New("--pod-selector=<pod_selector> must be a valid label selector")}}o.nodeInfos = []*resource.Info{}//构造Node info对象o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()//设置namespaceif err != nil {return err}o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) {//printflag转printer函数o.PrintFlags.NamePrintFlags.Operation = operationif o.drainer.DryRun {o.PrintFlags.Complete("%s (dry run)")}printer, err := o.PrintFlags.ToPrinter()if err != nil {return nil, err}return printer.PrintObj, nil}builder := f.NewBuilder().WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).NamespaceParam(o.Namespace).DefaultNamespace().ResourceNames("nodes", args...).SingleResourceType().Flatten()//用builder构造result对象if len(o.drainer.Selector) > 0 {builder = builder.LabelSelectorParam(o.drainer.Selector).ResourceTypes("nodes")}r := builder.Do()//构造result对象if err = r.Err(); err != nil {return err}return r.Visit(func(info *resource.Info, err error) error {//visit result对象if err != nil {return err}if info.Mapping.Resource.GroupResource() != (schema.GroupResource{Group: "", Resource: "nodes"}) {//判断info为nodereturn fmt.Errorf("error: expected resource of type node, got %q", info.Mapping.Resource)}o.nodeInfos = append(o.nodeInfos, info)//append inforeturn nil})
}
//运行drain
func (o *DrainCmdOptions) RunDrain() error {if err := o.RunCordonOrUncordon(true); err != nil {//先执行cordonreturn err}printObj, err := o.ToPrinter("drained")//printflag转printerif err != nil {return err}drainedNodes := sets.NewString()//定义drainedNodesvar fatal errorfor _, info := range o.nodeInfos {//遍历nodeinfovar err errorif !o.drainer.DryRun {//如果非干跑err = o.deleteOrEvictPodsSimple(info)//删除或驱逐pod}if err == nil || o.drainer.DryRun {//如果是干跑或者错误为空,drainedNode添加drainedNodes.Insert(info.Name)printObj(info.Object, o.Out)//打印结果} else {// 如果非干跑fmt.Fprintf(o.ErrOut, "error: unable to drain node %q, aborting command...\n\n", info.Name)//打印错误remainingNodes := []string{}fatal = errfor _, remainingInfo := range o.nodeInfos {//遍历Node infoif drainedNodes.Has(remainingInfo.Name) {//如果drainedNodes包含info则跳过continue}remainingNodes = append(remainingNodes, remainingInfo.Name)//append没有drained的node}if len(remainingNodes) > 0 {//如果剩余的node大于0fmt.Fprintf(o.ErrOut, "There are pending nodes to be drained:\n")for _, nodeName := range remainingNodes {//打印提示fmt.Fprintf(o.ErrOut, " %s\n", nodeName)}}break}}return fatal
}
//删除或驱逐pod
func (o *DrainCmdOptions) deleteOrEvictPodsSimple(nodeInfo *resource.Info) error {list, errs := o.drainer.GetPodsForDeletion(nodeInfo.Name)//获取node下的需要删除的podif errs != nil {return utilerrors.NewAggregate(errs)}if warnings := list.Warnings(); warnings != "" {//打印告警fmt.Fprintf(o.ErrOut, "WARNING: %s\n", warnings)}if err := o.drainer.DeleteOrEvictPods(list.Pods()); err != nil {//执行删除或驱逐podpendingList, newErrs := o.drainer.GetPodsForDeletion(nodeInfo.Name)//获取没有被删除或驱逐的podfmt.Fprintf(o.ErrOut, "There are pending pods in node %q when an error occurred: %v\n", nodeInfo.Name, err)//打印告警for _, pendingPod := range pendingList.Pods() {//打印pod pendingfmt.Fprintf(o.ErrOut, "%s/%s\n", "pod", pendingPod.Name)}if newErrs != nil {fmt.Fprintf(o.ErrOut, "following errors also occurred:\n%s", utilerrors.NewAggregate(newErrs))}return err}return nil
}
//执行删除或驱逐pod
func (d *Helper) DeleteOrEvictPods(pods []corev1.Pod) error {if len(pods) == 0 {//pod为空返回return nil}policyGroupVersion, err := CheckEvictionSupport(d.Client)//判断是否支持evictif err != nil {return err}// TODO(justinsb): unnecessary?getPodFn := func(namespace, name string) (*corev1.Pod, error) {//获取pod的函数return d.Client.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})}if len(policyGroupVersion) > 0 {//如果支持驱逐return d.evictPods(pods, policyGroupVersion, getPodFn)//驱逐pod}return d.deletePods(pods, getPodFn)//删除pod
}
//驱逐pod
func (d *Helper) evictPods(pods []corev1.Pod, policyGroupVersion string, getPodFn func(namespace, name string) (*corev1.Pod, error)) error {returnCh := make(chan error, 1)//创建return channelfor _, pod := range pods {//遍历podgo func(pod corev1.Pod, returnCh chan error) {//运行go routinefor {fmt.Fprintf(d.Out, "evicting pod %q\n", pod.Name)//打印驱逐poderr := d.EvictPod(pod, policyGroupVersion)//执行驱逐podif err == nil {//如果error为nil,跳出循环break} else if apierrors.IsNotFound(err) {returnCh <- nil//如果报没找到错误,往channel里放nilreturn} else if apierrors.IsTooManyRequests(err) {//如果错误是太多请求fmt.Fprintf(d.ErrOut, "error when evicting pod %q (will retry after 5s): %v\n", pod.Name, err)time.Sleep(5 * time.Second)//休息5秒} else {returnCh <- fmt.Errorf("error when evicting pod %q: %v", pod.Name, err)//往channel放一个错误return}}_, err := waitForDelete([]corev1.Pod{pod}, 1*time.Second, time.Duration(math.MaxInt64), true, getPodFn, d.OnPodDeletedOrEvicted)//等待pod删除完成if err == nil {//error为空,往channel放nilreturnCh <- nil} else {//否则往channel放错误returnCh <- fmt.Errorf("error when waiting for pod %q terminating: %v", pod.Name, err)}}(pod, returnCh)//调用go routine}doneCount := 0//完成数量var errors []error// 0 timeout means infinite, we use MaxInt64 to represent it.var globalTimeout time.Duration//全局超时时间if d.Timeout == 0 {//如果没有指定超时,则为最大整数globalTimeout = time.Duration(math.MaxInt64)} else {//如果指定了超时,则指定超时时间globalTimeout = d.Timeout}globalTimeoutCh := time.After(globalTimeout)//超时channelnumPods := len(pods)//需要evit的pod数量for doneCount < numPods {//如果完成数量不等于需要完成的数量,则一直循环select {case err := <-returnCh://从channel里获取值doneCount++//完成数量加1if err != nil {//如果有错误append错误errors = append(errors, err)}case <-globalTimeoutCh://如果超时,返回错误return fmt.Errorf("drain did not complete within %v", globalTimeout)}}return utilerrors.NewAggregate(errors)
}
//执行删除pod
func (d *Helper) deletePods(pods []corev1.Pod, getPodFn func(namespace, name string) (*corev1.Pod, error)) error {// 0 timeout means infinite, we use MaxInt64 to represent it.var globalTimeout time.Duration//设置超时时间if d.Timeout == 0 {globalTimeout = time.Duration(math.MaxInt64)} else {globalTimeout = d.Timeout}for _, pod := range pods {//遍历pod执行删除err := d.DeletePod(pod)if err != nil && !apierrors.IsNotFound(err) {return err}}_, err := waitForDelete(pods, 1*time.Second, globalTimeout, false, getPodFn, d.OnPodDeletedOrEvicted)//等待删除完成return err
}

kubectl源码分析之drain相关推荐

  1. kubectl源码分析之config delete-context

    欢迎关注我的公众号: 目前刚开始写一个月,一共写了18篇原创文章,文章目录如下: istio多集群探秘,部署了50次多集群后我得出的结论 istio多集群链路追踪,附实操视频 istio防故障利器,你 ...

  2. kubectl源码分析之cordon and uncordon

    欢迎关注我的公众号: 目前刚开始写一个月,一共写了18篇原创文章,文章目录如下: istio多集群探秘,部署了50次多集群后我得出的结论 istio多集群链路追踪,附实操视频 istio防故障利器,你 ...

  3. kubectl源码分析之auth reconcile

    欢迎关注我的公众号: 目前刚开始写一个月,一共写了18篇原创文章,文章目录如下: istio多集群探秘,部署了50次多集群后我得出的结论 istio多集群链路追踪,附实操视频 istio防故障利器,你 ...

  4. kubectl源码分析之taint

    欢迎关注我的公众号: 目前刚开始写一个月,一共写了18篇原创文章,文章目录如下: istio多集群探秘,部署了50次多集群后我得出的结论 istio多集群链路追踪,附实操视频 istio防故障利器,你 ...

  5. JDK源码分析 NIO实现

    总列表:http://hg.openjdk.java.net/ 小版本:http://hg.openjdk.java.net/jdk8u jdk:http://hg.openjdk.java.net/ ...

  6. celery源码分析-worker初始化分析(下)

    celery源码分析 本文环境python3.5.2,celery4.0.2,django1.10.x系列 celery的worker启动 在上文中分析到了Hub类的初始化,接下来继续分析Pool类的 ...

  7. supervisor源码分析

    Supervisor分析 1.运行原理概述: Supervisor生成主进程并将主进程变成守护进程,supervisor依次生成配置文件中的工作进程,然后依次监控工作进程的工作状态,并且主进程负责与s ...

  8. kubeadm源码分析(内含kubernetes离线包,三步安装)

    k8s离线安装包 三步安装,简单到难以置信 kubeadm源码分析 说句实在话,kubeadm的代码写的真心一般,质量不是很高. 几个关键点来先说一下kubeadm干的几个核心的事: kubeadm ...

  9. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  10. stream pipe的原理及简化源码分析

    前言 在编写代码时,我们应该有一些方法将程序像连接水管一样连接起来 -- 当我们需要获取一些数据时,可以去通过"拧"其他的部分来达到目的.这也应该是IO应有的方式. -- Doug ...

最新文章

  1. (续)我对09毕业生说两句
  2. “大众搬家”何其多啊?[3/14/2007 update]
  3. 链接多个数据库的方法
  4. 数字孪生技术从概念走向实际应用
  5. 与 OpenCV 1 同时使用
  6. 《Python Cookbook 3rd》笔记(4.1):手动遍历迭代器
  7. 搜索引擎技术之网络爬虫
  8. 文件和内建函数 open() 、file()
  9. 爬虫入门系列(四):HTML 文本解析库 BeautifulSoup
  10. 小程序block标签配合if和else 和 动态修改标题栏
  11. Java连接各种数据库
  12. HTML期末学生大作业-最新QQ音乐、网易云音乐、酷狗音乐、虾米音乐、咪咕音乐网站html+css+javascript
  13. PPT中导出高分辨率图片的方法
  14. 1125 斐波那契数列
  15. Python关键词百度指数采集,抓包Cookie及json数据处理
  16. DocumentBuilderFactory.newInstance() 异常解决
  17. 文件流转换为base64码 和 base64码转换为文件流
  18. JWTUtil工具类使用
  19. .net rar zip压缩包解压
  20. 手写Fbank语音特征提取

热门文章

  1. 简单人物画像_简易人物画像作品
  2. 计算机毕业设计-基于springboot的社区志愿者管理系统
  3. USB转SPI芯片操作FLASH--CH347应用
  4. iOS展示超大图片或超高分辨率图片崩溃解决方法
  5. 删除计算机文件的几种方法,3种方式删除目录中的所有文件,除了一个或少量带扩展名的文件...
  6. 电脑如何分盘win10_Win10电脑如何刻录光盘?利用win10自带刻录工具来刻录DVD光盘教程...
  7. MySQL3:连接查询、子查询及正则表达式查询
  8. oracle 工具ODM,oracle ODM 数据挖掘笔记
  9. Vue中@click.stop与@click.prevent、@click.native
  10. DeepFool论文阅读