Calico 源码分析:initContainers /opt/cni/bin/install

441 阅读2分钟

部署Calico网络插件时,initContainers部分初始化操作做了什么?

# kubectl get ds calico-node -n kube-system -o yaml
      initContainers:
        # This container installs the CNI binaries
        # and CNI network config file on each node.
        - name: install-cni
          image: registry.geoway.com/calico/cni:v3.19.1
          command: ["/opt/cni/bin/install"]

源码分析

  • cni-plugin/cmd/calico/calico.go
func main() {
	// Use the name of the binary to determine which routine to run.
	_, filename := filepath.Split(os.Args[0])
	switch filename {
        // ...
	case "install":
		err := install.Install() // => 安装相关证书和二进制可执行
		if err != nil {
			logrus.WithError(err).Fatal("Error installing CNI plugin")
		}
	default:
		panic("Unknown binary name: " + filename)
	}
}
  • cni-plugin/pkg/install/install.go
func Install() error {

        // ...
	// Load config.
	c := loadConfig()

	// Determine if we're running as a Kubernetes pod.
	var kubecfg *rest.Config

        // 安装TLS证书

	// Copy over any TLS assets from the SECRETS_MOUNT_DIR to the host.
	// First check if the dir exists and has anything in it.
	if directoryExists(c.TLSAssetsDir) {
		logrus.Info("Installing any TLS assets")
		mkdir("/host/etc/cni/net.d/calico-tls")
		if err := copyFileAndPermissions(fmt.Sprintf("%s/%s", c.TLSAssetsDir, "etcd-ca"), "/host/etc/cni/net.d/calico-tls/etcd-ca"); err != nil {
			logrus.Warnf("Missing etcd-ca")
		}
		if err := copyFileAndPermissions(fmt.Sprintf("%s/%s", c.TLSAssetsDir, "etcd-cert"), "/host/etc/cni/net.d/calico-tls/etcd-cert"); err != nil {
			logrus.Warnf("Missing etcd-cert")
		}
		if err := copyFileAndPermissions(fmt.Sprintf("%s/%s", c.TLSAssetsDir, "etcd-key"), "/host/etc/cni/net.d/calico-tls/etcd-key"); err != nil {
			logrus.Warnf("Missing etcd-key")
		}
	}
        // 运行时/host/opt/cni/bin会映射到宿主机的/opt/cni/bin
	// Place the new binaries if the directory is writeable.
	dirs := []string{"/host/opt/cni/bin", "/host/secondary-bin-dir"}
	binsWritten := false
	for _, d := range dirs {
		if err := fileutil.IsDirWriteable(d); err != nil {
			logrus.Infof("%s is not writeable, skipping", d)
			continue
		}

		// Iterate through each binary we might want to install.
		files, err := ioutil.ReadDir("/opt/cni/bin/")
		if err != nil {
			log.Fatal(err)
		}
                // 拷贝二进制文件calico calico-ipam etc.
		for _, binary := range files {
			target := fmt.Sprintf("%s/%s", d, binary.Name())
			source := fmt.Sprintf("/opt/cni/bin/%s", binary.Name())
			if c.skipBinary(binary.Name()) {
				continue
			}
			if fileExists(target) && !c.UpdateCNIBinaries {
				logrus.Infof("Skipping installation of %s", target)
				continue
			}
			if err := copyFileAndPermissions(source, target); err != nil {
				logrus.WithError(err).Errorf("Failed to install %s", target)
				os.Exit(1)
			}
			logrus.Infof("Installed %s", target)
		}


                // calico -v 检查是否拷贝成功
		// Print CNI plugin version to confirm that the binary was actually written.
		// If this fails, it means something has gone wrong so we should retry.
		cmd := exec.Command(d+"/calico", "-v")
		var out bytes.Buffer
		cmd.Stdout = &out
		err = cmd.Run()

	}

	// Write a CNI config file.
	writeCNIConfig(c)
	return nil
}

  • writeCNIConfig(c)

writeCNIConfig(c)根据模板,环境变量 etc. 生成calico的CNI配置文件/etc/cni/net.d/10-calico.conflist

比如我的环境下的/etc/cni/net.d/10-calico.conflist:

{
  "name": "k8s-pod-network",
  "cniVersion": "0.3.1",
  "plugins": [
    {
      "type": "calico",
      "log_level": "info",
      "log_file_path": "/var/log/calico/cni/cni.log",
      "etcd_endpoints": "https://${k8s_master_ip}:2379",
      "etcd_key_file": "/etc/cni/net.d/calico-tls/etcd-key",
      "etcd_cert_file": "/etc/cni/net.d/calico-tls/etcd-cert",
      "etcd_ca_cert_file": "/etc/cni/net.d/calico-tls/etcd-ca",
      "mtu": 0,
      "ipam": {
          "type": "calico-ipam"
      },
      "policy": {
          "type": "k8s"
      },
      "kubernetes": {
          "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
      }
    },
    {
      "type": "portmap",
      "snat": true,
      "capabilities": {"portMappings": true}
    },
    {
      "type": "bandwidth",
      "capabilities": {"bandwidth": true}
    }
  ]
}