前提条件

  • 节点配置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

vim /etc/sysconfig/network-scripts/ifcfg-XXX
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
systemctl restart network

测试ipv4

ping 10.20.13.90

测试ipv6

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

节点开启ipv6(所有节点)

vim /etc/sysctl.d/k8s.conf
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
sysctl --system

k8s开启双栈(主节点)

修改kube-apiserver

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

修改kube-controller-manager

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

修改kube-proxy

kubectl edit cm -n kube-system kube-proxy

重启kube-proxy容器

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

calico 配置双栈

kubectl edit cm -n kube-system calico-config
"ipam": {
    "type": "calico-ipam",
    "assign_ipv4": "true",
    "assign_ipv6": "true"
},

kubectl edit ds -n kube-system calico-node
# 设置自动获取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"

等待calico重启

修改kubeadm-config

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

kubectl edit cm -n kube-system kubeadm-config

验证

查看ipv6地址池

kubectl get ippool

pod获取ipv6地址

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

kubectl delete pod -n xxxx xxxxxx-xxx-xxx --force

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

services配置双栈

kubectl edit svc -n xxxx xxxxx-svc

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

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

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

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

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

kubectl describe svc -n xxxx xxxxxx-svc

service示例

新增service单栈ipv6

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双栈

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)