kubeadm-join
0
总安装量
1
周安装量
安装命令
npx skills add https://github.com/sigridjineth/kubespray-skills --skill kubeadm-join
Agent 安装分布
windsurf
1
amp
1
cline
1
opencode
1
cursor
1
kimi-cli
1
Skill 文档
kubeadm join – Node Cluster Membership
Overview
kubeadm join adds nodes to an existing cluster through bidirectional trust establishment.
Core principle: Join requires two-way trust – the node must verify the control plane (Discovery), and the control plane must verify the node (TLS Bootstrap).
When to Use
- Adding worker nodes to cluster
- Adding control plane nodes for HA
- Troubleshooting node join failures
- Understanding TLS bootstrap mechanism
Bidirectional Trust
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â BIDIRECTIONAL TRUST â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â Discovery (Node â Control Plane) â
â âââââââââââââââââââââââââââââââââ â
â "Is this API Server legitimate?" â
â Method: CA cert hash verification or kubeconfig file â
â â
â TLS Bootstrap (Control Plane â Node) â
â ââââââââââââââââââââââââââââââââââââ â
â "Is this node authorized to join?" â
â Method: Bootstrap token â CSR â Certificate issuance â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Basic Join Command
From kubeadm init output:
kubeadm join 192.168.10.100:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:xxxx...
| Component | Purpose |
|---|---|
192.168.10.100:6443 |
API Server endpoint |
--token |
Bootstrap token (used for both discovery and TLS bootstrap) |
--discovery-token-ca-cert-hash |
CA certificate fingerprint (prevents MITM) |
Worker Node Join
Phases
1. preflight â Check requirements
2. discovery â Get cluster-info, verify CA
3. TLS bootstrap â Authenticate with token, submit CSR, get certificate
4. kubelet-start â Configure and start kubelet
Command
kubeadm join 192.168.10.100:6443 \
--token 123456.1234567890123456 \
--discovery-token-ca-cert-hash sha256:bd763182...
Post-Join Files (Worker)
/etc/kubernetes/
âââ kubelet.conf # kubelet kubeconfig
âââ pki/
âââ ca.crt # Cluster CA (for verification)
/var/lib/kubelet/
âââ config.yaml # kubelet configuration
âââ kubeadm-flags.env # Extra kubelet flags
Control Plane Node Join (HA)
Additional Phases
1. preflight
2. discovery
3. control-plane-prepare â Download certs, generate manifests
4. TLS bootstrap
5. etcd-join â Add to etcd cluster
6. kubelet-start
7. control-plane-join â Apply labels/taints
Command
kubeadm join 192.168.10.100:6443 \
--token 123456.1234567890123456 \
--discovery-token-ca-cert-hash sha256:bd763182... \
--control-plane \
--certificate-key <certificate-key>
Get Certificate Key
# On existing control plane
kubeadm init phase upload-certs --upload-certs
# Outputs: certificate-key: <64-char-hex>
# Or during initial kubeadm init
kubeadm init --upload-certs
Token Management
List Tokens
kubeadm token list
Create New Token
# Simple
kubeadm token create
# With join command
kubeadm token create --print-join-command
# With custom TTL
kubeadm token create --ttl 2h
Get CA Hash
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
Discovery Methods
Token-Based (Default)
kubeadm join ... --token xxx --discovery-token-ca-cert-hash sha256:xxx
- Fetches
cluster-infoConfigMap fromkube-publicnamespace - Verifies CA with provided hash
File-Based
kubeadm join ... --discovery-file /path/to/cluster-info.yaml
- Uses pre-distributed kubeconfig file
- For air-gapped or highly secure environments
Unsafe (Not Recommended)
kubeadm join ... --discovery-token-unsafe-skip-ca-verification
- Skips CA verification
- Vulnerable to MITM attacks
TLS Bootstrap Flow
New Node Control Plane
ââââââââ âââââââââââââ
â â
âââââ 1. Get cluster-info âââââââââââ¶â (unauthenticated)
âââââ CA cert + API endpoint âââââââââ
â â
âââââ 2. Authenticate with token ââââ¶â
âââââ Temporary credentials ââââââââââ
â â
âââââ 3. Submit CSR âââââââââââââââââ¶â
â â (auto-approved)
âââââ 4. Signed certificate ââââââââââ
â â
âââââ 5. Use certificate ââââââââââââ¶â (full kubelet access)
â â
Configuration File Approach
# join-config.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: "192.168.10.100:6443"
token: "123456.1234567890123456"
caCertHashes:
- "sha256:bd763182..."
nodeRegistration:
kubeletExtraArgs:
node-ip: "192.168.10.101"
criSocket: "unix:///run/containerd/containerd.sock"
kubeadm join --config=join-config.yaml
Common Issues
| Symptom | Cause | Fix |
|---|---|---|
| Connection refused to 6443 | Firewall blocking | Open port 6443 on control plane |
| Token expired / “could not find JWS signature” | Default 24h TTL | kubeadm token create --print-join-command |
| CA hash mismatch | Wrong hash or different cluster | Get correct hash from control plane |
| TLS bootstrap timeout | Network/firewall issue | Check connectivity, firewalld |
| Node shows wrong IP | Multi-NIC, wrong default | Set node-ip in kubeletExtraArgs |
| x509 certificate error | Clock skew | Sync NTP on all nodes |
Note: The error “could not find a JWS signature in the cluster-info ConfigMap for token ID” means your bootstrap token has expired. The JWS signature is removed from cluster-info when the token expires.
Troubleshooting Steps
1. Verify API Server Reachability
# From worker node
curl -k https://192.168.10.100:6443/healthz
# Expected: "ok"
2. Check Token Validity
# On control plane
kubeadm token list
# Check expiration time
3. Verify Network
# From worker â verify control plane API is reachable
ping 192.168.10.100
curl -k https://192.168.10.100:6443/healthz # Should return "ok"
4. Check Firewall
# On control plane
systemctl is-active firewalld
# If active, open required ports or disable
firewall-cmd --permanent --add-port=6443/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --reload
5. Check kubelet Logs
journalctl -u kubelet -f
Reset and Retry
# On the node that failed to join
kubeadm reset -f
rm -rf /etc/kubernetes /var/lib/kubelet
iptables -F && iptables -t nat -F
# Re-attempt join
kubeadm join ...
Verification Checklist
After successful join:
- Node appears in
kubectl get nodes - Node becomes Ready (after CNI installed)
-
kubeletservice running:systemctl status kubelet - kube-proxy running:
crictl ps | grep proxy -
/etc/kubernetes/kubelet.confexists -
/var/lib/kubelet/config.yamlexists
cluster-info ConfigMap
The bootstrap process depends on this publicly-accessible ConfigMap:
# View (works without authentication)
curl -k https://192.168.10.100:6443/api/v1/namespaces/kube-public/configmaps/cluster-info
# Contains:
# - kubeconfig: API Server address + CA certificate
# - jws-kubeconfig-<token>: Signed verification
This is the ONLY Kubernetes resource accessible without authentication.