本指南解释了如何在没有kube-proxy的情况下配置Kubernetes集群,以及如何使用Cilium完全替换它。为了简单起见,我们将使用kubeadm引导集群。
有关安装kubeadm的帮助和更多配置选项,请参阅kubeadm官方文档。
Cilium的kubeProxyReplacement依赖于socket LB功能,这需要v4.19.57、v5.1.16、v5.2.0或更高版本的Linux内核。Linux内核v5.3和v5.8添加了Cilium可以用来进一步优化kube代理替换实现的其他功能。
注意,v5.0.x已经处于EOL阶段且没有运行kube-proxy替换所需的修复程序
快速开始
通过kubeadm init
初始化控制平面节点,并跳过kube-proxy插件的安装:
根据您使用的CRI实现,您可能需要在
kubeadm init…
命令中使用--cri-socket
选项定制CRI。例如:如果您使用的是Docker CRI,您将使用--cri-socket unix:///var/run/cri-dockerd.sock
。
kubeadm init --skip-phases=addon/kube-proxy
然后,通过指定控制平面节点IP地址和kubeadm init返回的令牌来加入工作节点(对于本教程,至少要向集群添加一个工作节点):
kubeadm join <..>
如果您有多个网络接口,请确保在每个worker上正确设置kubelet的
--node-ip
。否则,Cilium的kube-proxy 替换可能无法正常工作。您可以通过运行kubectl get nodes-owide
来验证这一点,以查看每个节点是否具有分配给每个节点上具有相同名称的设备的InternalIP
。
对于已经通过DaemonSet安装了kube-proxy的集群,请使用以下命令将kube-proxy其删除。注意:该操作断开现有的服务连接,停止与服务相关的通信,直到安装了cilium替换:
$ kubectl -n kube-system delete ds kube-proxy
$ # Delete the configmap as well to avoid kube-proxy being reinstalled during a Kubeadm upgrade (works only for K8s 1.19 and newer)
$ kubectl -n kube-system delete cm kube-proxy
$ # Run on each node with root permissions:
$ iptables-save | grep -v KUBE | iptables-restore
注意请使用helm3完成本教程的安装操作,helm2是不兼容的。
设置helm仓库:
helm repo add cilium https://helm.cilium.io/
接下来,生成所需的YAML文件并部署它们。重要:请通过kubeadm init
报告的kube-apiserver IP地址和端口号确认你设置的 API_SERVER_IP
和API_SERVER_PORT
正确(kubeadm默认使用端口6443)。
因为kubeadm init
是在没有kube-proxy的情况下直接运行,所以必须要设置这两个环境变量。尽管kubeadm将KUBERNETES_SERVICE_HOST
和KUBERNETES_SERVICE_PORT
使用ClusterIP的模式导出到环境变量中。但没有kube-proxy,网络是不通的。因此,需要通过以下配置使cilium了解该信息:
API_SERVER_IP=<your_api_server_ip>
# Kubeadm default is 6443
API_SERVER_PORT=<your_api_server_port>
helm install cilium cilium/cilium --version 1.12.1 \
--namespace kube-system \
--set kubeProxyReplacement=strict \
--set k8sServiceHost=${
API_SERVER_IP} \
--set k8sServicePort=${
API_SERVER_PORT}
Cilium将自动在默认路径路径
/run/cilium/cgroupv2
上挂载附加BPF cgroupv2程序所需的cgroup2文件系统。为此,它需要daemonset的init容器挂载主机/proc路径。通过--set cgroup.autoMount.enabled=false
可禁用自动挂载,并通过使用--set cgroup.hostRoot
设置一个已经在主机挂载的cgroup v2文件系统。例如,如果尚未安装,可以通过在主机上运行mount -t cgroup2 none /sys/fs/cgroup
命令来安装cgroup v2文件系统,然后早helm安装命令设置参数--set cgroup.hostRoot=/sys/fs/cgroup
。
helm最终将cilium安装为一个CNI插件,并使用eBPF kube-proxy replacement来实现实现对ClusterIP、NodePort、LoadBalancer类型的Kubernetes服务和具有ExternalIP的服务的处理。此外,eBPF kube-proxy replacement还支持容器的hostPort,因此不再需要使用portmap插件。
最后,验证cilium正确的在集群中安装,并准备好提供网络服务。
$ kubectl -n kube-system get pods -l k8s-app=cilium
NAME READY STATUS RESTARTS AGE
cilium-fmh8d 1/1 Running 0 10m
cilium-mkcmb 1/1 Running 0 10m
注意,在上述Helm配置中,kubeProxyReplacement
已设置为严格(strict
)模式。这意味着,如果缺少底层Linux内核支持,Cilium agent将直接退出。
默认情况下,Helm将kubeProxyReplacement
设置为disabled
,这意味着cilium仅对集群内的ClusterIP服务启用的负载平衡。
Cilium在直接路由和隧道模式中都支持eBPF kube-proxy replacement。
验证设置
在使用上述快速入门指南部署Cilium之后,我们可以首先验证Cilium代理是否以所需模式运行:
$ kubectl -n kube-system exec ds/cilium -- cilium status | grep KubeProxyReplacement
KubeProxyReplacement: Strict [eth0 (Direct Routing), eth1]
使用--verbose
选项可以查看更多详细信息。
$ kubectl -n kube-system exec ds/cilium -- cilium status --verbose
[...]
KubeProxyReplacement Details:
Status: Strict
Socket LB: Enabled
Protocols: TCP, UDP
Devices: eth0 (Direct Routing), eth1
Mode: SNAT
Backend Selection: Random
Session Affinity: Enabled
Graceful Termination: Enabled
NAT46/64 Support: Enabled
XDP Acceleration: Disabled
Services:
- ClusterIP: Enabled
- NodePort: Enabled (Range: 30000-32767)
- LoadBalancer: Enabled
- externalIPs: Enabled
- HostPort: Enabled
[...]
下一步,我们将创建一个Nginx部署。然后,我们将创建一个新的NodePort服务,并验证Cilium是否能正确处理网络服务。
以下yaml用于创建后端Pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
验证nginx pod启动并进入running阶段。
$ kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-756fb87568-gmp8c 1/1 Running 0 62m 10.217.0.149 apoc <none> <none>
my-nginx-756fb87568-n5scv 1/1 Running 0 62m 10.217.0.107 apoc <none> <none>
接下来,为两个pod创建NodePort类型的service。
$ kubectl expose deployment my-nginx --type=NodePort --port=80
service/my-nginx exposed
验证NodePort类型的service是否创建成功。
$ kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx NodePort 10.104.239.135 <none> 80:31940/TCP 24m
通过cilium service list
命令,我们可以验证cilium的eBPF kube-proxy replacement创建了新的NodePort