kubernetes集群升级ipv4/ipv6双栈

前提条件

  • 节点配置ipv4/ipv6地址
  • k8s集群<=1.23
  • 安装calico插件>=3.23

地址规划

网络 ipv4 ipv6
pod-cidr 10.244.0.0/16 2000::/112
service-cidr 10.96.0.0/12 3000::/112

注意:ipv6掩码位需要>=108,否则kube-apiserver会报错

网卡同时配置ipv4/ipv6

1
vim /etc/sysconfig/network-scripts/ifcfg-XXX
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=yes
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=yes
IPV6_ADDR_GEN_MODE=stable-privacy
IPV6ADDR=2031:0:130c::90 # 改为实际的ipv6地址
IPV6_DEFAULTGW=2031:0:130c::1 # 改为实际的ipv6网关地址
IPV6_DEFROUTE=yes
DEVICE=ens192
ONBOOT=yes
IPADDR=10.20.13.90
PREFIX=24
GATEWAY=10.20.13.1
DNS1=218.2.2.2
DNS2=2001:4860:4860::8888 # ipv6 dns 不用动
IPV6_PRIVACY=no
1
systemctl restart network

测试ipv4

1
ping 10.20.13.90

测试ipv6

1
ping -6 2031:0:130c::90

节点开启ipv6(所有节点)

1
vim /etc/sysctl.d/k8s.conf
1
2
3
4
5
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
net.ipv6.conf.all.forwarding = 1
1
sysctl --system

k8s开启双栈(主节点)

修改kube-apiserver

1
vim /etc/kubernetes/manifests/kube-apiserver.yaml
1
--service-cluster-ip-range=10.96.0.0/12,3000::/112

image-20240424154319890

修改kube-controller-manager

1
vim /etc/kubernetes/manifests/kube-controller-manager.yaml

image-20240424154354671

修改kube-proxy

1
kubectl edit cm -n kube-system kube-proxy

image-20240424155114938

重启kube-proxy容器

1
kubectl get pod -n kube-system | grep kube-proxy | awk '{print $1}' | xargs kubectl delete pod -n kube-system

calico 配置双栈

1
kubectl edit cm -n kube-system calico-config
1
2
3
4
5
"ipam": {
"type": "calico-ipam",
"assign_ipv4": "true",
"assign_ipv6": "true"
},

image-20240424155614010

1
kubectl edit ds -n kube-system calico-node
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 设置自动获取ipv6地址
- name: IP6
value: autodetect
# felix启用ipv6支持
- name: FELIX_IPV6SUPPORT
value: "true"
# 设置ipv6地址池,与pod-cidr一致,官方说使用kubeadm安装的集群不需要配置,但是没试过。
- name: CALICO_IPV6POOL_CIDR
value: 2000::/112
# pod通信使用vxlan封装,如果节点跨子网,使容器之间可以访问
- name: CALICO_IPV6POOL_VXLAN
value: CrossSubnet
# 开启ipv6 NAT功能,使容器可以访问外部的ipv6地址
- name: CALICO_IPV6POOL_NAT_OUTGOING
value: "true"

image-20240424160040807

等待calico重启

修改kubeadm-config

上方修改的apiserver、controller-manager是静态文件,如果集群升级kubeadm-config会重置静态文件,导致ipv6的配置消失,所以将这个配置文件同时修改

1
kubectl edit cm -n kube-system kubeadm-config

image-20240425091454939

验证

查看ipv6地址池

1
kubectl get ippool

image-20240424160631893

pod获取ipv6地址

重启pod,查看获取的ipv6地址

1
2
3
kubectl delete pod -n xxxx xxxxxx-xxx-xxx --force

kubectl get pod - n xxxx xxxxxx-xxx-xxx -o jsonpath={.status.podIPs}

image-20240424161315923

services配置双栈

1
kubectl edit svc -n xxxx xxxxx-svc

image-20240424161359493

  • SingleStack:单栈 Service。控制面使用第一个配置的服务集群 IP 范围为 Service 分配集群 IP

  • PreferDualStack:为 Service 分配 IPv4 和 IPv6 集群 IP 地址。

  • RequireDualStack:从 IPv4 和 IPv6 的地址范围分配 Service 的ClusterIPs

    ipFamilies 数组中第一个ip地址的 ClusterIPs作为ClusterIP

注意:ipFamilies 字段修改是有条件的:你可以添加或删除第二个 IP 地址族, 但你不能更改现有 Service 的主要 IP 地址。

1
kubectl describe svc -n xxxx xxxxxx-svc

image-20240424162335499

service示例

新增service单栈ipv6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
ipFamilies:
- IPv6
ipFamilyPolicy: SingleStack
ports:
- nodePort: 30080
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: NodePort

service双栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
ipFamilies:
- IPv6
- IPv4
ipFamilyPolicy: PreferDualStack
ports:
- nodePort: 30081
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: NodePort

参考链接:IPv4/IPv6 双协议栈 | Kubernetes自定义 Calico 配置 |Calico 文档 (tigera.io)