docker pull quay.io/coreos/flannel
quay.io/coreos/flannel:v0.10.0-arm
kubectl describe pod kube-flannel-ds-7r68t -n kube-system
docker pull quay.io/kubespray/flannel-cni-plugin
https://quay.io/kubespray/flannel-cni-plugin?spm=5176.28103460.0.0.40f7451e5gF1b9&tab=tags
https://quay.io/repository/chengyuzhu6/rancher/mirrored-flannelcni-flannel-cni-plugin?spm=5176.28103460.0.0.40f7451e5gF1b9&tab=tags
v1.1.0
sudo yum install -y skopeo # CentOS/RHEL
https://quay.io/repository/coreos/flannel?spm=5176.28103460.0.0.40f7451e5gF1b9&tab=tags
https://quay.io/kubespray/flannel-cni-plugin?spm=5176.28103460.0.0.40f7451e5gF1b9&tab=tags
docker pull quay.io/coreos/flannel:v0.15.1
是node3节点 对应公网的ip 是192.168.1.116(zerotier组网分配)
是node4节点 对应公网的ip 是192.168.1.117(zerotier组网分配)
/etc/hosts
本地回环地址
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
主节点本地IP与主机名映射
192.168.242.128 k8s-master
工作节点本地IP与主机名映射
192.168.242.129 k8s-node-1
192.168.242.130 k8s-node-2
192.168.242.131 k8s-node-3 # 假设Node3的本地IP为192.168.242.131
192.168.242.132 k8s-node-4 # 假设Node4的本地IP为192.168.242.132
ZeroTier公网IP与主机名映射
192.168.1.146 k8s-master
192.168.1.232 k8s-node-1
192.168.1.115 k8s-node-2
192.168.1.116 k8s-node-3
192.168.1.117 k8s-node-4
sudo kubeadm init
–kubernetes-version=v1.18.8
–apiserver-advertise-address=192.168.1.146 \ # ZeroTier公网IP(主节点)
–pod-network-cidr=10.244.0.0/16
–apiserver-cert-extra-sans=
192.168.1.146, \ # 主节点的公网IP
192.168.242.128, \ # 主节点本地IP
k8s-master, \ # 主节点主机名
127.0.0.1, \ # 默认项
kubernetes.default, \ # 默认项
192.168.1.232, \ # Node1的公网IP
192.168.1.115, \ # Node2的公网IP
192.168.1.116, \ # Node3的公网IP
192.168.1.117 # Node4的公网IP
你的观察是正确的,在某些情况下,仅配置主节点的本地IP和公网IP(即 --apiserver-cert-extra-sans
中仅包含主节点的IP)可能也能成功启动集群。但需要明确以下几点:
1. 为什么可能成功?
场景分析:
-
节点通过主节点的公网IP连接 API Server:
- 当节点执行
kubeadm join
时,会通过主节点的公网IP(如192.168.1.146
)连接 API Server。 - 只要主节点的公网IP和本地IP被包含在证书的 SAN 列表中,节点就能通过主节点的 IP 成功连接,无需其他节点的公网IP。
- 当节点执行
-
节点之间通过本地网络通信:
- 节点的本地IP(如
192.168.242.129
)用于集群内部通信(如 Pod 网络、kubelet 通信),这些 IP 通常不需要包含在 API Server 的证书中,因为它们不直接用于连接 API Server。
- 节点的本地IP(如
2. 为什么需要包含其他节点的公网IP?
关键场景:
-
节点需要通过自己的公网IP连接 API Server:
- 如果节点尝试通过自己的公网IP(如
192.168.1.232
)连接 API Server,则证书必须包含该 IP,否则会因证书验证失败而无法连接。 - 例如,如果节点的防火墙或网络配置强制要求通过自己的公网IP访问 API Server,则必须包含该 IP。
- 如果节点尝试通过自己的公网IP(如
-
高可用集群(HA)或多网络环境:
- 在高可用集群中,API Server 可能部署在多个节点上,每个节点的公网IP都需要包含在证书中。
- 如果节点分布在不同网络或需要通过多个入口访问 API Server,则必须将所有相关 IP 加入证书。
3. 你的配置中是否需要其他节点的公网IP?
根据你的描述:
- 当前配置:
- 主节点的公网IP是
192.168.1.146
,且所有节点通过该 IP 加入集群。 - 其他节点的公网IP(如
192.168.1.232
、192.168.1.115
等)未被包含在证书的 SAN 列表中。
- 主节点的公网IP是
结论:
- 如果节点仅通过主节点的公网IP连接 API Server,则无需包含其他节点的公网IP,集群仍可正常运行。
- 但存在潜在风险:
- 如果后续需要通过其他节点的公网IP直接访问 API Server(例如,某些特定网络策略或故障转移场景),则证书会因缺少这些 IP 而导致连接失败。
4. 完整的证书配置建议
最小必要配置:
sudo kubeadm init \
--apiserver-cert-extra-sans= \
192.168.1.146, \ # 主节点的公网IP
192.168.242.128, \ # 主节点的本地IP
k8s-master, \ # 主节点的主机名(可选,但推荐)
127.0.0.1, \ # 默认项
kubernetes.default # 默认项
推荐配置(覆盖所有可能性):
sudo kubeadm init \
--apiserver-cert-extra-sans= \
192.168.1.146, \ # 主节点的公网IP
192.168.242.128, \ # 主节点的本地IP
k8s-master, \ # 主节点的主机名
127.0.0.1, \ # 默认项
kubernetes.default, \ # 默认项
192.168.1.232, \ # Node1的公网IP(可选,按需添加)
192.168.1.115, \ # Node2的公网IP(可选,按需添加)
192.168.1.116, \ # Node3的公网IP(可选,按需添加)
192.168.1.117 # Node4的公网IP(可选,按需添加)
5. 具体场景下的建议
场景1:仅通过主节点公网IP连接
- 配置:仅包含主节点的公网IP和本地IP。
- 适用情况:所有节点通过主节点的公网IP加入集群,且后续无需直接通过其他节点的公网IP访问 API Server。
- 潜在风险:如果后续需要直接通过其他节点的公网IP访问 API Server(例如跨网络故障转移),会导致证书错误。
场景2:需要多入口访问
- 配置:包含所有节点的公网IP。
- 适用情况:集群需要高可用性,或节点可能通过多个公网IP访问 API Server(例如分布式网络)。
- 优势:避免因证书 SAN 列表不足导致的连接问题。
6. 验证证书的 SAN 列表
执行以下命令检查证书是否包含必要的 IP:
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | grep "X509v3 Subject Alternative Name"
预期输出示例:
X509v3 Subject Alternative Name:
DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local,
IP Address:127.0.0.1, IP Address:192.168.1.146, IP Address:192.168.242.128,
DNS:k8s-master
7. 总结
- 最小必要配置:只需包含主节点的公网IP和本地IP即可启动集群。
- 推荐配置:包含所有节点的公网IP以覆盖所有可能的连接场景,避免未来扩展时出现证书问题。
- 实际需求决定配置:根据你的网络拓扑和访问方式选择配置,但建议覆盖所有可能的 IP 以确保可靠性。
如果当前集群运行正常且无扩展需求,可以暂时仅配置主节点的 IP。但若未来需要通过其他节点的公网IP访问 API Server,需重新初始化集群并更新证书。
/cni/net.d/*
sudo ip link delete cni0
sudo ip link delete flannel.1
rm -rf $HOME/.kube/
sudo netstat -tuln | grep -E ‘6443|10259|10257|10250|2379|2380’
kubeadm init --kubernetes-version=v1.18.8 --apiserver-advertise-address=192.168.1.146 --pod-network-cidr=10.244.0.0/16 --apiserver-cert-extra-sans=192.168.1.146【这里只是指定公网的ip 太少了 通过master本地假如的话认证就有问题 所以后面需要加入本地的ip】
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown
(
i
d
−
u
)
:
(id -u):
(id−u):(id -g) $HOME/.kube/config
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master NotReady master 65s v1.18.8
[root@k8s-master ~]#
sudo vim /etc/hosts
185.199
EXTRA GROUPS
odc9wj.7x4p14dkhyzd2xml 21h 2025-03-28T09:21:01-07:00 authentication,signing The default bootstrap token generated by ‘kubeadm init’. system:bootstrappers:kubeadm:default-node-token
[root@k8s-master ~]#
[root@k8s-master ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed ‘s/^.* //’
a18443cf1099c9d705a5cc4d4e17da2722d23e1f2696324f6d9c740791d583ce
[root@k8s-master ~]#
kubeadm join 192.168.242.128:6443
–token odc9wj.7x4p14dkhyzd2xml
–discovery-token-ca-cert-hash sha256:a18443cf1099c9d705a5cc4d4e17da2722d23e1f2696324f6d9c740791d583ce
- 当前
kubeadm join 192.168.242.128:6443
–token odc9wj.7x4p14dkhyzd2xml
–discovery-token-ca-cert-hash sha256:a18443cf1099c9d705a5cc4d4e17da2722d23e1f2696324f6d9c740791d583ce - 当前证书配置
从你的命令来看,API Server 的证书只包含了 192.168.1.146(通过 --apiserver-cert-extra-sans 参数指定)。因此,工作节点通过 192.168.242.128 连接时会报错:
Plaintext
深色版本
x509: certificate is valid for 10.96.0.1, 192.168.1.146, not 192.168.242.128
[root@k8s-master ~]# vi kubeadm-config.yaml
[root@k8s-master ~]# mv /etc/kubernetes/pki/apiserver.{crt,key} /tmp/
[root@k8s-master ~]# kubeadm init phase certs apiserver --config kubeadm-config.yaml
W0327 11:51:16.022367 19024 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[certs] Generating “apiserver” certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.242.128 192.168.1.146 192.168.242.128]
[root@k8s-master ~]#
[root@k8s-master ~]# docker ps | grep kube-apiserver | awk ‘{print $1}’ | xargs docker restart
e72be5dffe52
96beb2e6b323
[root@k8s-master ~]#
[root@k8s-master ~]# openssl s_client -connect 192.168.242.128:6443 -showcerts </dev/null 2>/dev/null | openssl x509 -text -noout | grep DNS
DNS:k8s-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, IP Address:10.96.0.1, IP Address:192.168.242.128, IP Address:192.168.1.146, IP Address:192.168.242.128
[root@k8s-master ~]#
[root@k8s-node-2 ~]# kubeadm join 192.168.242.128:6443 \
–token odc9wj.7x4p14dkhyzd2xml
–discovery-token-ca-cert-hash sha256:a18443cf1099c9d705a5cc4d4e17da2722d23e1f2696324f6d9c740791d583ce
W0327 11:53:09.577643 11207 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster…
[preflight] FYI: You can look at this config file with ‘kubectl -n kube-system get cm kubeadm-config -oyaml’
[kubelet-start] Downloading configuration for the kubelet from the “kubelet-config-1.18” ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file “/var/lib/kubelet/config.yaml”
[kubelet-start] Writing kubelet environment file with flags to file “/var/lib/kubelet/kubeadm-flags.env”
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap…
This node has joined the cluster:
- Certificate signing request was sent to apiserver and a response was received.
- The Kubelet was informed of the new secure connection details.
Run ‘kubectl get nodes’ on the control-plane to see this node join the cluster.
[root@k8s-node-2 ~]#
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 153m v1.18.8
k8s-node-1 Ready 38s v1.18.8
k8s-node-2 Ready 53s v1.18.8
[root@k8s-master ~]# [root@k8s-master ~]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-66bff467f8-8pv4g 1/1 Running 0 153m
coredns-66bff467f8-98vzg 1/1 Running 0 153m
etcd-k8s-master 1/1 Running 0 153m
kube-apiserver-k8s-master 1/1 Running 0 153m
kube-controller-manager-k8s-master 1/1 Running 0 153m
kube-flannel-ds-drdr4 1/1 Running 0 84s
kube-flannel-ds-gxz8l 1/1 Running 0 99s
kube-flannel-ds-q7pz5 1/1 Running 0 41m
kube-proxy-gjwrk 1/1 Running 0 99s
kube-proxy-mcpwp 1/1 Running 0 84s
kube-proxy-xhfdg 1/1 Running 0 153m
kube-scheduler-k8s-master 1/1 Running 0 153m
[root@k8s-master ~]#