前言
本文介绍在一个 Calico 作为缺省 CNI 的集群,通过 Spiderpool 这一完整的 Underlay 网络解决方案,通过 Multus 为 Pod 额外附加一张由 Macvlan 创建的网卡,为集群提供Underlay数据面。
1 环境介绍
- 集群环境:3个宿主机节点,已经使用Calico作为CNI,CIDR是197.166.0.0/16,k8s版本v1.23.6。
- Spiderpool 版本:v0.8.3
- Multus-CNI 版本:v3.9.3
- 预留的 Underlay IP:100.10.22.210~100.10.22.218
2 安装步骤
由于集群在一个内网环境,所以无法按照官网的指导进行操作。只能把helm的charts和依赖镜像下载到本地操作。
2.1 下载 cni charts 和镜像
- CNI
因为需要用到
macvlan
的CNI插件,所以要手动下载,这里下载的是v1.3.0 - Spiderpool charts 在 github spidernet-io/spiderpool 的 github_pages 这个分支,在 docs/charts/ 下找到对应版本——spiderpool-0.8.3.tgz。
- Spiderpool-controller 镜像
docker pull ghcr.io/spidernet-io/spiderpool/spiderpool-controller:v0.8.3
- Spiderpool-agent 镜像
docker pull ghcr.io/spidernet-io/spiderpool/spiderpool-agent:v0.8.3
- Multus-cni 镜像
docker pull ghcr.io//k8snetworkplumbingwg/multus-cni:v3.9.3
下载完成后将镜像使用docker save -o xxx.tar
保存成文件,和spiderpool-0.8.3.tgz一并拷贝到环境的宿主机上(集群所有宿主机都要有),并使用docker load -i xxx.tar
加载好镜像(注意加载后要恢复docker tag)。CNI解压后把macvlan的二进制放到集群所有宿主机的/opt/cni/bin
下面。
2.2 检查 kube-system/kubeadm-config ConfigMap
spiderpool 默认从 kubeadm-config 中获取 service 的子网信息,如果没有这个ConfigMap需要手动创建一个,简单的文件(kubeadm-config.yaml)如下:
代码语言:yaml复制networking:
podSubnet: 197.166.0.0/16
serviceSubnet: 169.169.0.0/16
注意里面的子网信息要和集群创建时的保持一致。
使用如下命令创建:
代码语言:bash复制kubectl create configmap kubeadm-config -n kube-system --from-file=./kubeadm-config.yaml
PS:目前 spiderpool v0.8.3 的版本还有这个依赖,已经给社区提了issue,后续版本可能会解除这个依赖。
2.3 安装
需要确保环境宿主机上已经有了helm。
- 解压缩 charts 并使用 Helm 更新依赖tar -xvf spiderpool-0.8.3.tgz
helm dep update ./spiderpool
- 安装Spiderpool
helm install spiderpool ./spiderpool --namespace kube-system --set coordinator.mode=overlay --wait
参数介绍
参数 | 作用 |
---|---|
coordinator.mode | 这里指定overlay才是作为第二个网卡 |
multus.multusCNI.defaultCniCRName | 指定 multus 默认使用的 CNI 的 NetworkAttachmentDefinition(NAD) 实例名。如果参数选项不为空,则安装后会自动生成一个数据为空的 NAD 对应实例。如果参数选项为空,会尝试通过 /etc/cni/net.d 目录下的第一个 CNI 配置来创建对应的 NAD 实例,否则会自动生成一个名为 default 的 NAD 实例 |
multus.install | 默认是自动安装multus,如果已经安装multus,先要显式设置为false |
- 安装完成后,查看 Spiderpool 组件状态
~# kubectl get pod -n kube-system | grep spiderpool
spiderpool-agent-9ffcc 1/1 Running 0 64s
spiderpool-agent-jq6sq 1/1 Running 0 64s
spiderpool-agent-kz8m4 1/1 Running 0 64s
spiderpool-controller-59bcd9985b-hz42m 1/1 Running 0 86s
spiderpool-init 1/1 Running 0 86s
- 检查 Spidercoordinator.status 中的 Phase 是否为 Synced, 并且 overlayPodCIDR 是否与集群中 Calico 的子网保持一致
~# calicoctl get ippools
NAME CIDR SELECTOR
default-ipv4-ippool 197.166.0.0/16 all()
default-ipv6-ippool fd97:6fea:542f::/48 all()
~# kubectl get spidercoordinators.spiderpool.spidernet.io default -o yaml
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderCoordinator
metadata:
creationTimestamp: "2023-12-26T06:04:24Z"
finalizers:
- spiderpool.spidernet.io
generation: 1
name: default
resourceVersion: "4407909"
selfLink: /apis/spiderpool.spidernet.io/v2beta1/spidercoordinators/default
uid: 64822833-357d-4f41-af81-262d22380a3b
spec:
detectGateway: false
detectIPConflict: false
hijackCIDR:
- 169.254.0.0/16
hostRPFilter: 0
hostRuleTable: 500
mode: overlay
podCIDRType: auto
podDefaultRouteNIC: ""
podMACPrefix: ""
tunePodRoutes: true
status:
overlayPodCIDR:
- 197.166.0.0/16
- fd97:6fea:542f::/48
phase: Synced
serviceCIDR:
- 169.169.0.0/16
(如果 phase 不为 Synced, 那么将会阻止 Pod 被创建,如果 overlayPodCIDR 不正常, 可能会导致通信问题)
- 创建 SpiderIPPool Underlay 的网卡 enp1s0 所在子网为 100.10.22.0/24,以该子网创建 SpiderIPPool:
cat << EOF | kubectl apply -f -
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderIPPool
metadata:
name: underlay-pool
spec:
disable: false
gateway: 100.10.22.134
ips:
- 100.10.22.210-100.10.22.218
subnet: 100.10.22.0/24
EOF
subnet 应该与节点网卡 enp1s0 的子网保持一致,并且 ips 不与现有任何 IP 冲突。
- 创建 SpiderMultusConfig 通过 Spidermultusconfig 创建 Multus 的 NAD 实例:
cat << EOF | kubectl apply -f -
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderMultusConfig
metadata:
name: macvlan-enp1s0
spec:
cniType: macvlan
macvlan:
master:
- enp1s0
ippools:
ipv4:
- underlay-pool
vlanID: 0
EOF
spec.macvlan.master 设置为 enp1s0, enp1s0 必须存在于主机上。并且 spec.macvlan.spiderpoolConfigPools.IPv4IPPool设置的子网和 enp1s0 保持一致。
创建成功后, 查看 Multus NAD 是否成功创建:
代码语言:bash复制kubectl get network-attachment-definitions.k8s.cni.cncf.io macvlan-enp1s0 -o yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"spiderpool.spidernet.io/v2beta1","kind":"SpiderMultusConfig","metadata":{"annotations":{},"name":"macvlan-enp1s0","namespace":"default"},"spec":{"cniType":"macvlan","macvlan":{"ippools":{"ipv4":["underlay-pool"]},"master":["enp1s0"],"vlanID":0}}}
creationTimestamp: "2023-12-27T02:21:40Z"
generation: 1
name: macvlan-enp1s0
namespace: default
ownerReferences:
- apiVersion: spiderpool.spidernet.io/v2beta1
blockOwnerDeletion: true
controller: true
kind: SpiderMultusConfig
name: macvlan-enp1s0
uid: daa7e75e-cf40-4112-a7a3-307ce2f94b52
resourceVersion: "4409741"
selfLink: /apis/k8s.cni.cncf.io/v1/namespaces/default/network-attachment-definitions/macvlan-enp1s0
uid: 20c156d0-c326-474c-86bb-21e7de0fdc5f
spec:
config: '{"cniVersion":"0.3.1","name":"macvlan-enp1s0","plugins":[{"type":"macvlan","master":"enp1s0","mode":"bridge","ipam":{"type":"spiderpool","default_ipv4_ippool":["underlay-pool"]}},{"detectIPConflict":false,"detectGateway":false,"mode":"auto","type":"coordinator"}]}'
3 创建一个带 Underlay 网卡的应用
我这里用go做了一个简单的http应用镜像,默认监听8080端口,收到请求后会返回所有IPv4地址。代码如下:
代码语言:go复制package main
import (
"encoding/json"
"fmt"
"net"
"net/http"
"os"
"runtime"
)
type Handler struct {
str []string
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s, _ := json.Marshal(h.str)
w.Write([]byte(s))
}
func main() {
runtime.GOMAXPROCS(2)
port, ok := os.LookupEnv("SERVER_PORT")
if !ok {
port = "8080"
}
addrs, err := net.InterfaceAddrs()
if err != nil {
fmt.Println(err)
return
}
ips := []string{}
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
ips = append(ips, ipnet.IP.String())
}
}
}
http.Handle("/", &Handler{ips})
if err = http.ListenAndServe(":" port, nil); err != nil {
fmt.Println(err.Error())
}
}
这里打包成一个httpd:0.0.1
的镜像。
使用下面的命令创建测试应用 httpd:
代码语言:bash复制cat << EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd
spec:
replicas: 1
selector:
matchLabels:
app: httpd
template:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: macvlan-enp1s0
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd:0.0.1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
EOF
PS:k8s.v1.cni.cncf.io/networks: 该字段指定 Multus 使用 macvlan-enp1s0 为 Pod 附加一张网卡。
等Pod Running状态后查看:
代码语言:bash复制kubectl describe pod httpd-85f96ddc76-7tjzt
中间省略...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 16m default-scheduler Successfully assigned default/httpd-85f96ddc76-7tjzt to 100.10.22.104
Normal AddedInterface 6m51s multus Add eth0 [197.166.25.41/32] from kube-system/k8s-pod-network
Normal AddedInterface 6m51s multus Add net1 [100.10.22.213/24] from default/macvlan-enp1s0
然后从同vlan其他主机访问Pod:
代码语言:bash复制curl 100.10.22.213:8080
["197.166.25.41","100.10.22.213"]
4 补充 IPv6 双栈
4.1 创建一个 v6 的 IPPool
代码语言:bash复制cat << EOF | kubectl apply -f -
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderIPPool
metadata:
name: underlay-pool-v6
spec:
disable: false
ips:
- 2001:db8::a00:64ff:fe0a:1691-2001:db8::a00:64ff:fe0a:1699
subnet: 2001:db8::/64
EOF
注意,这里没有加网关。
4.2 重新创建 Mutus 的 NAD 实例
代码语言:bash复制cat << EOF | kubectl apply -f -
apiVersion: spiderpool.spidernet.io/v2beta1
kind: SpiderMultusConfig
metadata:
name: macvlan-enp1s0
spec:
cniType: macvlan
macvlan:
master:
- enp1s0
ippools:
ipv4:
- underlay-pool
ipv6:
- underlay-pool-v6
vlanID: 0
EOF
这里我们增加了 v6 的IPPool。
4.3 参考 3 重新部署下 http 应用
等Pod Running状态后查看:
代码语言:bash复制kubectl describe pod httpd-85d54455d-6xdbw
中间省略...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 32s default-scheduler Successfully assigned default/httpd-85d54455d-6xdbw to 100.10.22.106
Normal AddedInterface 31s multus Add eth0 [197.166.54.137/32 fd00:c5a6::2a:609/128] from kube-system/k8s-pod-network
Normal AddedInterface 31s multus Add net1 [100.10.22.213/24 2001:db8::a00:64ff:fe0a:1691/64] from default/macvlan-enp1s0
Normal Pulled 31s kubelet Container image "http:1.0.0" already present on machine
Normal Created 30s kubelet Created container httpd
Normal Started 30s kubelet Started container httpd
可以看到Pod的网卡信息已经是双栈。
然后从同vlan其他主机访问Pod:
代码语言:bash复制curl -6 http://[2001:db8::a00:64ff:fe0a:1691]:8080
["197.166.25.41","100.10.22.213"]
总结
整个安装过程还算比较顺利,中间遇到的问题,项目组的同学帮助也非常及时,在此表示感谢@郭奇峰
参考内容:
Calico Quick Start