kubernetes 源码分析之ingress(二)

来源:互联网 发布:ansys软件培训 编辑:程序博客网 时间:2024/05/16 05:40

先看服务启动过程

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。
这样服务就可以启动了。

0 0
原创粉丝点击