简介
之前介绍过sigs.k8s.io controller-runtime系列之六 webhook分析sigs.k8s.io controller-runtime-webhook 。
本文主要介绍pkg/certwatcher的源码分析。
目录结构
- certwatcher.go
- CertWatcher结构体 监视证书和密钥文件的更改。当任何一个文件更改时,它调用读取和解析这两个函数,并使用新的证书。
type CertWatcher struct { sync.RWMutex // 解析后的证书文件内容 currentCert *tls.Certificate watcher *fsnotify.Watcher // 证书路径 certPath string // 证书key路径 keyPath string }
- New函数 通过给定的certPath和keyPath,创建一个新的证书监视器。
func New(certPath, keyPath string) (*CertWatcher, error) { var err error // 通过certPath和keyPath构造出CertWatcher对象的地址 cw := &CertWatcher{ certPath: certPath, keyPath: keyPath, } // 从文件读取证书文件 if err := cw.ReadCertificate(); err != nil { return nil, err } // 引用github.com/fsnotify/fsnotify构造的监视器,具体注意事项参考https://github.com/fsnotify/fsnotify的FAQ cw.watcher, err = fsnotify.NewWatcher() if err != nil { return nil, err } return cw, nil } // ReadCertificate从磁盘读取证书和密钥文件,并对其进行解析,并更新观察程序上的当前证书。如果设置了回调,则用新证书调用。 func (cw *CertWatcher) ReadCertificate() error { cert, err := tls.LoadX509KeyPair(cw.certPath, cw.keyPath) if err != nil { return err } cw.Lock() cw.currentCert = &cert cw.Unlock() log.Info("Updated current TLS certificate") return nil }
- Start函数 启动cerwatcher,监视certificate and key 文件
func (cw *CertWatcher) Start(ctx context.Context) error { files := []string{cw.certPath, cw.keyPath} // 添加到监视文件中 for _, f := range files { if err := cw.watcher.Add(f); err != nil { return err } } // 目前必须开启单独的goruntime监视,参考https://github.com/fsnotify/fsnotify的FAQ go cw.Watch() log.Info("Starting certificate watcher") // Block until the context is done. <-ctx.Done() return cw.watcher.Close() } // 从监视器管道中读取事件,并及时响应 func (cw *CertWatcher) Watch() { for { select { case event, ok := <-cw.watcher.Events: // 通道已关闭 if !ok { return } // 处理给定事件 cw.handleEvent(event) case err, ok := <-cw.watcher.Errors: // 通道已关闭 if !ok { return } log.Error(err, "certificate watch error") } } } func (cw *CertWatcher) handleEvent(event fsnotify.Event) { // 仅仅关心修改了file内容的event if !(isWrite(event) || isRemove(event) || isCreate(event)) { return } log.V(1).Info("certificate event", "event", event) // 如果文件被移除,则重新添加到监视文件中 if isRemove(event) { if err := cw.watcher.Add(event.Name); err != nil { log.Error(err, "error re-watching file") } } if err := cw.ReadCertificate(); err != nil { log.Error(err, "error re-reading certificate") } } // 判断是否写入事件 func isWrite(event fsnotify.Event) bool { return event.Op&fsnotify.Write == fsnotify.Write } // 判断是否创建事件 func isCreate(event fsnotify.Event) bool { return event.Op&fsnotify.Create == fsnotify.Create } // 判断是否移除事件 func isRemove(event fsnotify.Event) bool { return event.Op&fsnotify.Remove == fsnotify.Remove }