Kubernetes 网络升级:安装 Cilium 用上 eBPF(基于阿里云弹性网卡ENI)
之前网络组件用的是 calico,本来想基于 calico 启用 eBPF,但折腾多次没有成功,详见博文 Kubernetes 集群尝试基于 Calico 启用 eBPF。
于是改用 cilium,这篇博文简单记录一下安装步骤,官方帮助文档 Setting Up Cilium in AlibabaCloud ENI Mode
确认 linux 内核版本 Kernel >= 5.10
,不然无法启用 eBPF Host-Routing,详见 https://q.cnblogs.com/q/139828/
在 阿里云 RAM 访问控制
控制台添加子账号
- 添加用户
cilium
,访问方式是Open API 调用访问
- 得到
AccessKey ID
与AccessKey Secret
- 添加下面的名为
ENIAccess
的授权策略,并授权给cilium
用户
{
"Version": "1",
"Statement": [{
"Action": [
"ecs:CreateNetworkInterface",
"ecs:DescribeNetworkInterfaces",
"ecs:AttachNetworkInterface",
"ecs:DetachNetworkInterface",
"ecs:DeleteNetworkInterface",
"ecs:DescribeInstanceAttribute",
"ecs:DescribeInstanceTypes",
"ecs:AssignPrivateIpAddresses",
"ecs:UnassignPrivateIpAddresses",
"ecs:DescribeInstances"
],
"Resource": [
"*"
],
"Effect": "Allow"
},
{
"Action": [
"vpc:DescribeVSwitches",
"vpc:ListTagResources"
],
"Resource": [
"*"
],
"Effect": "Allow"
}
]
}
- 除了添加上面的权限,还需要添加
AliyunVPCReadOnlyAccess
权限(只读访问专有网络(VPC)的权限) - 在 k8s 集群中创建 secret 并保存 AccessKey ID 与 AccessKey Secret(用
echo -n "access_key" | base64
命令编码)
apiVersion: v1
kind: Secret
metadata:
name: cilium-alibabacloud
namespace: kube-system
type: Opaque
data:
ALIBABA_CLOUD_ACCESS_KEY_ID: ""
ALIBABA_CLOUD_ACCESS_KEY_SECRET: ""
采用 helm 安装 cilium
helm repo add cilium https://helm.cilium.io/
helm upgrade cilium cilium/cilium --version 1.11.4 \
--install \
--namespace kube-system \
--set alibabacloud.enabled=true \
--set ipam.mode=alibabacloud \
--set enableIPv4Masquerade=false \
--set tunnel=disabled
安装 cilium cli
curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-amd64.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
rm cilium-linux-amd64.tar.gz{,.sha256sum}
强制重启所有 pod 以使用 cilium
kubectl get pods --all-namespaces -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOSTNETWORK:.spec.hostNetwork --no-headers=true | grep '<none>' | awk '{print "-n "$1" "$2}' | xargs -L 1 -r kubectl delete pod --force --grace-period 0
检查 cilium pod 是否已正常启动
$ kubectl get pods -l k8s-app=cilium -n kube-system -o wide 130 ↵
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cilium-587m5 1/1 Running 0 10h 10.0.9.198 kube-temp3-16c16g <none> <none>
检查 cilium 的运作状态
阿里云弹性网卡控制台可以看到 pod 所使用的弹性网卡
接下来用 cilium 取代 kube-proxy。
注:阿里云负载均衡与 Cilium’s kube-proxy replacement 存在兼容问题,暂时不能使用这种方式,详见 https://q.cnblogs.com/q/139841/
先禁用 kube-proxy
kubectl patch ds -n kube-system kube-proxy -p '{"spec":{"template":{"spec":{"nodeSelector":{"non-cilium": "true"}}}}}'
然后设置 kubeProxyReplacement
helm upgrade cilium cilium/cilium --version 1.11.4 \
--namespace kube-system \
--set kubeProxyReplacement=strict \
--set k8sServiceHost=k8s-api \
--set k8sServicePort=6443
注:k8sServiceHost
与 k8sServicePort
是 api-server 的主机名与端口号,可以通过下面的命令获取
kubectl get configmap -n kube-system kube-proxy -o yaml | grep server
确认是否成功取代 kube-proxy
$ kubectl exec -it -n kube-system ds/cilium -- cilium status | grep KubeProxyReplacement
Defaulted container "cilium-agent" out of: cilium-agent, mount-cgroup (init), clean-cilium-state (init)
KubeProxyReplacement: Strict [eth0 10.0.9.171 (Direct Routing), tunl0 192.168.69.192]
KubeProxyReplacement: Strict
说明已成功取代。
Cilium 取代 kube-proxy 之后,通过 service NodePort 暴露的端口在 node 服务器上用 netstat -lntp
命令查看不到,要通过 cilium 命令查看
$ kubectl exec -it -n kube-system daemonset/cilium -- cilium service list
...
130 0.0.0.0:31080 NodePort 1 => 10.0.4.215:80
测试 NodePort 是否可以连上
$ telnet 10.0.9.206 31080
Trying 10.0.9.206...
Connected to 10.0.9.206.
Escape character is '^]'.
Cilium 安装完成,成功用上 eBPF!
收尾工作
在每天节点删除 kube-proxy 生成的 iptables 配置
iptables-save | grep -v KUBE | iptables-restore
删除 calico
kubectl delete -f calico.yaml
删除 kube-proxy
$ # 首先备份 kube-system ConfigMap
$ kubectl get cm kube-proxy -n kube-system -o yaml > kube-proxy-cm.yaml
$ kubectl -n kube-system delete ds kube-proxy
$ kubectl -n kube-system delete cm kube-proxy