部署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}
}
]
}