kubernetes 源码分析之ingress(二)

先看服务启动过程

func main() {
    // start a new nginx controller
    ngx := newNGINXController()
    // create a custom Ingress controller using NGINX as backend
    ic := controller.NewIngressController(ngx)
    go handleSigterm(ic)
    // start the controller
    ic.Start()
    // wait
    glog.Infof("shutting down Ingress controller...")
    for {
        glog.Infof("Handled quit, awaiting pod deletion")
        time.Sleep(30 * time.Second)
    }
}

这里定义了服务的启动和停止,先创建NewIngressController然后启动ic.Start(),如果停止通过SIGTERM信号关闭,停止的代码很简单,先解决

func handleSigterm(ic *controller.GenericController) {
    signalChan := make(chan os.Signal, 1)
    signal.Notify(signalChan, syscall.SIGTERM)
    <-signalChan
    glog.Infof("Received SIGTERM, shutting down")

    exitCode := 0
    if err := ic.Stop(); err != nil {
        glog.Infof("Error during shutdown %v", err)
        exitCode = 1
    }

    glog.Infof("Exiting with %v", exitCode)
    os.Exit(exitCode)
}

很简单,就是接受SIGTERM调用Stop方法,Stop方法里面把同步queue关闭。讲完关闭,回到开始创建的地方。

func newNGINXController() ingress.Controller {
    ngx := os.Getenv("NGINX_BINARY")
    if ngx == "" {
        ngx = binary
    }
    n := &NGINXController{
        binary:    ngx,
        configmap: &api.ConfigMap{},
    }

    var onChange func()
    onChange = func() {
        template, err := ngx_template.NewTemplate(tmplPath, onChange)
        if err != nil {
            // this error is different from the rest because it must be clear why nginx is not working
            glog.Errorf(`
-------------------------------------------------------------------------------
Error loading new template : %v
-------------------------------------------------------------------------------
`, err)
            return
        }

        n.t.Close()
        n.t = template
        glog.Info("new NGINX template loaded")
    }

    ngxTpl, err := ngx_template.NewTemplate(tmplPath, onChange)
    if err != nil {
        glog.Fatalf("invalid NGINX template: %v", err)
    }
    n.t = ngxTpl
    go n.Start()
    return ingress.Controller(n)
}

创建一个Nginx的controller,里没有有两个重要的参数:nginx的二进制文件和configmap。其实还有第三个字段是t(n.t = ngxTpl),它是一个Template结构体,主要负责修改nginx的配置文件

func NewTemplate(file string, onChange func()) (*Template, error) {
    tmpl, err := text_template.New("nginx.tmpl").Funcs(funcMap).ParseFiles(file)
    if err != nil {
        return nil, err
    }
    fw, err := watch.NewFileWatcher(file, onChange)
    if err != nil {
        return nil, err
    }

    return &Template{
        tmpl:      tmpl,
        fw:        fw,
        s:         defBufferSize,
        tmplBuf:   bytes.NewBuffer(make([]byte, 0, defBufferSize)),
        outCmdBuf: bytes.NewBuffer(make([]byte, 0, defBufferSize)),
    }, nil
}

加载的是nginx.tmpl的模板文件。那么模板文件是啥呢?

   client_header_buffer_size       {{ $cfg.ClientHeaderBufferSize }};
    large_client_header_buffers     {{ $cfg.LargeClientHeaderBuffers }};

    http2_max_field_size            {{ $cfg.HTTP2MaxFieldSize }};
    http2_max_header_size           {{ $cfg.HTTP2MaxHeaderSize }};

    types_hash_max_size             2048;
    server_names_hash_max_size      {{ $cfg.ServerNameHashMaxSize }};
    server_names_hash_bucket_size   {{ $cfg.ServerNameHashBucketSize }};
    map_hash_bucket_size            {{ $cfg.MapHashBucketSize }};

是gotemplate模板,里面有很多变量,当组织好结构后就可以通过替换变量,并且写入到nginx.conf里面。从而更新nginx配置。

然后启动nginx, go n.Start()

func (n *NGINXController) Start() {
    glog.Info("starting NGINX process...")

    done := make(chan error, 1)
    cmd := exec.Command(n.binary, "-c", cfgPath)
    n.start(cmd, done)
    for {
        err := <-done
        if exitError, ok := err.(*exec.ExitError); ok {
            waitStatus := exitError.Sys().(syscall.WaitStatus)
            glog.Warningf(`
-------------------------------------------------------------------------------
NGINX master process died (%v): %v
-------------------------------------------------------------------------------
`, waitStatus.ExitStatus(), err)
        }
        cmd.Process.Release()
        cmd = exec.Command(n.binary, "-c", cfgPath)
        // we wait until the workers are killed
        for {
            conn, err := net.DialTimeout("tcp", "127.0.0.1:80", 1*time.Second)
            if err != nil {
                break
            }
            conn.Close()
            time.Sleep(1 * time.Second)
        }
        // start a new nginx master process
        n.start(cmd, done)
    }
}

上面代码创建了nginx controller,ingress设计中nginx只是其中一种负载均衡,所以ic := controller.NewIngressController(ngx) 其中ic为ingress controller,在这个方法里面创建了调用k8s api的客户端,最终启动ingress的controller:ic.Start()

func (ic GenericController) Start() {
    glog.Infof("starting Ingress controller")

    go ic.ingController.Run(ic.stopCh)
    go ic.endpController.Run(ic.stopCh)
    go ic.svcController.Run(ic.stopCh)
    go ic.nodeController.Run(ic.stopCh)
    go ic.secrController.Run(ic.stopCh)
    go ic.mapController.Run(ic.stopCh)

    go ic.secretQueue.Run(5*time.Second, ic.stopCh)
    go ic.syncQueue.Run(5*time.Second, ic.stopCh)

    if ic.syncStatus != nil {
        go ic.syncStatus.Run(ic.stopCh)
    }

    <-ic.stopCh
}

这个方法是重点,这里面启动了对ingress、endpoint、service、node、secret、configmap的listwatch。还有两个对列secretQueue和syncQueue。
这样服务就可以启动了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳清风09

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值