刚接触Kubernetes的新手经常会遇到一个奇怪的现象:明明集群已经搭建好了,但节点状态却显示"NotReady"。这其实是因为Kubernetes本身并不提供网络功能,它需要网络插件来实现Pod之间的通信。Calico就是目前最流行的选择之一。
我在第一次部署Kubernetes集群时也踩过这个坑。当时花了两天时间排查各种配置,最后才发现是忘了装网络插件。Calico之所以成为首选,主要是因为它采用了纯三层网络模型,性能接近物理网络,而且支持丰富的网络策略。简单来说,它能让你的Kubernetes集群像传统网络一样可靠,同时保持云原生架构的灵活性。
虽然官方说最小2核2G就能跑,但我建议生产环境至少给每个节点4核8G。去年我们有个项目用2核4G的配置,Pod稍微多点就直接OOM了。具体到这次演示,我用的是三台CentOS 7.9的虚拟机:
注意:所有节点需要保持时间同步,建议安装ntpdate并同步阿里云的时间服务器
这些配置在所有节点上都要执行。我整理了一个一键执行的脚本:
bash复制#!/bin/bash
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭selinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 关闭swap
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
# 设置主机名
hostnamectl set-hostname $(basename $0 .sh)
# 加载内核模块
cat <<EOF | tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
# 内核参数
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
Kubernetes 1.24+已经不再强制依赖Docker,但考虑到兼容性,我们还是选择Docker作为容器运行时。这里有个小技巧:使用阿里云镜像源能大幅提升下载速度。
bash复制# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 设置仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装指定版本(推荐20.10.x)
yum install -y docker-ce-20.10.17 docker-ce-cli-20.10.17 containerd.io
# 配置镜像加速
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"registry-mirrors": ["https://registry.cn-hangzhou.aliyuncs.com"]
}
EOF
# 启动服务
systemctl enable docker && systemctl start docker
这里有个坑要注意:kubelet在安装后直接启动会失败,这是正常现象,等初始化完成就好了。
bash复制# 添加阿里云Kubernetes源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 安装三件套(指定版本避免兼容性问题)
yum install -y kubelet-1.23.8 kubeadm-1.23.8 kubectl-1.23.8
# 设置开机启动
systemctl enable kubelet
先创建一个初始化配置文件,这比直接使用命令行参数更便于维护:
bash复制kubeadm config print init-defaults > init-config.yaml
然后修改几个关键参数:
yaml复制apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.100.131 # 修改为master节点IP
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
imagePullPolicy: IfNotPresent
name: k8s-master
taints: null
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers # 使用国内镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.23.8
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 192.168.0.0/16 # 这个要匹配Calico的默认配置
scheduler: {}
开始初始化:
bash复制kubeadm init --config=init-config.yaml --upload-certs | tee kubeadm-init.log
初始化完成后,按照提示配置kubectl:
bash复制mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
在master节点上查看加入命令:
bash复制kubeadm token create --print-join-command
然后在每个node节点执行输出的命令,格式类似:
bash复制kubeadm join 192.168.100.131:6443 --token xxxx --discovery-token-ca-cert-hash sha256:xxxx
Calico版本需要与Kubernetes版本匹配。对于1.23.x集群,我推荐Calico v3.22:
bash复制curl https://docs.projectcalico.org/manifests/calico.yaml -O
国内用户可能会遇到镜像拉取问题,可以提前修改yaml中的镜像地址:
bash复制sed -i 's|docker.io/calico/|registry.cn-hangzhou.aliyuncs.com/calico/|g' calico.yaml
找到CALICO_IPV4POOL_CIDR配置项,确保与init-config.yaml中的podSubnet一致:
yaml复制- name: CALICO_IPV4POOL_CIDR
value: "192.168.0.0/16"
如果节点有多个网卡,需要指定使用的网卡:
yaml复制- name: IP_AUTODETECTION_METHOD
value: "interface=eth.*" # 根据实际情况调整
应用配置文件:
bash复制kubectl apply -f calico.yaml
检查部署状态:
bash复制watch kubectl get pods -n kube-system
正常情况下,几分钟后应该能看到所有Pod都变成Running状态。可以通过以下命令进一步验证:
bash复制# 检查节点状态
kubectl get nodes -o wide
# 检查Calico组件状态
kubectl get pods -n kube-system -l k8s-app=calico-node
# 创建测试Pod验证网络
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80
kubectl get svc,pod -o wide
这是我遇到最多的问题,通常有几个原因:
排查步骤:
bash复制# 查看节点详细信息
kubectl describe node <node-name>
# 查看Calico日志
kubectl logs -n kube-system <calico-pod-name>
# 检查网络连接
ping <pod-ip>
curl -I <service-ip>
这通常是因为主机防火墙没关或者路由有问题:
bash复制# 检查路由表
ip route show
# 测试基础网络
ping <other-node-ip>
telnet <other-node-ip> 8472 # Calico使用的UDP端口
对于生产环境,我建议调整这些参数:
yaml复制# 在calico.yaml中添加
- name: FELIX_IPTABLESREFRESHINTERVAL
value: "60s"
- name: FELIX_IPV6SUPPORT
value: "false"
- name: FELIX_LOGSEVERITYSCREEN
value: "info"
Calico最强大的功能之一是网络策略控制。比如只允许特定Pod访问数据库:
yaml复制apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-access
spec:
podSelector:
matchLabels:
role: db
ingress:
- from:
- podSelector:
matchLabels:
role: api
ports:
- protocol: TCP
port: 5432
对于大型集群,可以配置BGP与物理网络设备对接:
bash复制cat <<EOF | kubectl apply -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: peer-to-router
spec:
peerIP: 192.168.100.1
asNumber: 64512
EOF
建议部署Calico的监控组件:
bash复制kubectl apply -f https://docs.projectcalico.org/manifests/calico-monitoring.yaml
然后可以在Prometheus中配置相关告警规则,比如节点BGP会话中断、IP地址耗尽等。