RKE IPv4/IPv6 双栈高可用集群搭建
搭建说明
由于业务需要,集群需采用IPv6进行通信,经了解与实践,采用虚拟机方式实现IPv4/IPv6双栈高可用集群搭建与访问验证。
参考连接:
RKE Dual-stack配置
安装IPv4-IPv6双栈集群
部署环境
操作系统:Centos7.9
Docker: 24.0.7 (可使用20.10.x版本)
RKE:1.5.0
主机列表
名称 | IPv4 | IPv6 | 主机名 | 配置 | 组件 |
---|---|---|---|---|---|
k8s管理平台节点1 | 192.168.0.202 | fd15:4ba5:5a2b:1008:20c:29ff:fef0:7e45 | CT2 | 4C 4G 50G | controlplane,etcd,worker |
k8s管理平台节点1 | 192.168.0.203 | fd15:4ba5:5a2b:1008:20c:29ff:fedc:24c7 | CT3 | 4C 4G 50G | controlplane,etcd,worker |
k8s管理平台节点1 | 192.168.0.204 | fd15:4ba5:5a2b:1008:20c:29ff:fe31:22ea | CT4 | 4C 4G 50G | controlplane,etcd,worker |
Docker 安装请参考:Centos7.x版本docker与cuda安装
VMware Workstation 启用ipv6支持
编辑–>虚拟网络编辑器
由于需要修改网络配置,需管理员执行:选择VMnet8–>更改设置
勾选启用IPv6选项,IPv6前缀可自定义
保存后,操作系统可使用dhclient -v
自动获取命令获取ipv6地址
dhclient -v
IPv6地址配置
IPv6地址临时有效,写入网卡配置文件保存重启网卡进行固定ip
vim /etc/sysconfig/network-scripts/ifcfg-ens32
TYPE=Ethernet
BOOTPROTO=static
DEVICE=ens32
ONBOOT=yes
IPADDR=192.168.0.202
NETMASK=255.255.255.0
GATEWAY=192.168.0.2
DNS1=192.168.0.2
#ipv6 set
IPV6INIT=yes
IPV6_AUTOCONF=no
IPV6_FAILURE_FATAL=no
IPV6ADDR=fd15:4ba5:5a2b:1008:20c:29ff:fef0:7e45/64
IPV6_DEFAULTGW=fe80::250:56ff:fec0:2222
保存重启网卡生效
systemctl restart network
内核调优(ipv6 设置)
注意:若net.ipv6.conf.all.forwarding=1
参数已提前添加到配置中,执行dhclient -v
命令可能不会自动获取到IPv6地址
echo "
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.conf.all.forwarding=1
net.ipv6.conf.all.forwarding=1
net.ipv4.neigh.default.gc_thresh1=4096
net.ipv4.neigh.default.gc_thresh2=6144
net.ipv4.neigh.default.gc_thresh3=8192
net.ipv4.neigh.default.gc_interval=60
net.ipv4.neigh.default.gc_stale_time=120
# 参考 https://github.com/prometheus/node_exporter#disabled-by-default
kernel.perf_event_paranoid=-1
#sysctls for k8s node config
net.ipv4.tcp_slow_start_after_idle=0
net.core.rmem_max=16777216
fs.inotify.max_user_watches=524288
kernel.softlockup_all_cpu_backtrace=1
kernel.softlockup_panic=0
kernel.watchdog_thresh=30
fs.file-max=2097152
fs.inotify.max_user_instances=8192
fs.inotify.max_queued_events=16384
vm.max_map_count=262144
fs.may_detach_mounts=1
net.core.netdev_max_backlog=16384
net.ipv4.tcp_wmem=4096 12582912 16777216
net.core.wmem_max=16777216
net.core.somaxconn=32768
net.ipv4.ip_forward=1
net.ipv4.tcp_max_syn_backlog=8096
net.ipv4.tcp_rmem=4096 12582912 16777216
#net.ipv6.conf.all.disable_ipv6=1
#net.ipv6.conf.default.disable_ipv6=1
#net.ipv6.conf.lo.disable_ipv6=1
kernel.yama.ptrace_scope=0
vm.swappiness=0
# 可以控制core文件的文件名中是否添加pid作为扩展。
kernel.core_uses_pid=1
# Do not accept source routing
net.ipv4.conf.default.accept_source_route=0
net.ipv4.conf.all.accept_source_route=0
# Promote secondary addresses when the primary address is removed
net.ipv4.conf.default.promote_secondaries=1
net.ipv4.conf.all.promote_secondaries=1
# Enable hard and soft link protection
fs.protected_hardlinks=1
fs.protected_symlinks=1
# 源路由验证
# see details in https://help.aliyun.com/knowledge_detail/39428.html
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.conf.all.arp_announce=2
# see details in https://help.aliyun.com/knowledge_detail/41334.html
net.ipv4.tcp_max_tw_buckets=5000
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_synack_retries=2
kernel.sysrq=1
#redis优化
vm.overcommit_memory = 1
" > /etc/sysctl.conf
#执行sysctl -p 生效
sysctl -p
RKE集群搭建
创建普通用户: rke
用户名可自定义
[root@CT2 ~]# passwd rke
Changing password for user rke.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
[root@CT2 ~]# usermod -aG docker rke
[root@CT2 ~]# su - rke
Last login: Tue Dec 5 10:05:28 CST 2023 on pts/0
[rke@CT2 ~]$ docker info
ssh免密认证:
ssh-keygen
免密配置
ssh-copy-id 192.168.0.202
# 其他节点主机按相同方式添加
登录测试(可选操作)
验证登录是否免密直接登录
RKE工具下载
RKE国内下载地址
rke 工具仅在管理节点中一台上进行操作即可
wget https://rancher-mirror.rancher.cn/rke/v1.5.0/rke_linux-amd64
重命名与修改权限,移动到/usr/local/bin
mv rke_linux-amd64 rke
chmod +x rke
mv rke /usr/local/bin/
[rke@CT2 ~]$ rke --version
rke version v1.5.0
rke集群配置文件
rke集群网络:https://docs.rancher.cn/docs/rke/config-options/dual-stack/_index/
要求#
为了使用 Dual-stack 功能,RKE 和它所部署的基础设施必须配置如下:
使用 Kubernetes 1.21 或更新版本。
RKE 配置为使用 Calico 作为容器网络接口(CNI)提供商。不支持其他供应商。
RKE 部署在具有以下先决条件的 Amazon EC2 实例上:
启用 IPv6 支持:在 VPC 及其子网设置网络范围。
在 VPC 路由中添加一个 IPv6 默认网关。
在集群的安全组中添加 IPv6 流量的入站/出站规则。
确保实例已启用 Auto-assign IPv6 IP。请参阅 AWS 文档了解相关说明。
禁用集群中所有实例的源/目的地检查。请参阅 AWS 文档 以了解相关说明。
主要参数配置:
kubernetes_version: "v1.21.1-rancher2-1"
services:
kube-api:
service_cluster_ip_range: 10.43.0.0/16,fd98::/108
kube-controller:
service_cluster_ip_range: 10.43.0.0/16,fd98::/108
cluster_cidr: 10.42.0.0/16,fd01::/64
network:
plugin: calico
编辑RKE配置文件
vim rancher-cluster.yml
nodes:
- address: 192.168.0.202
#- address: "fd15:4ba5:5a2b:1008:20c:29ff:fef0:7e45"
user: rke
role: [controlplane, worker, etcd]
hostname_override: CT2
#labels:
# master: true
- address: 192.168.0.203
#- address: [fd15:4ba5:5a2b:1008:20c:29ff:fedc:24c7]
user: rke
hostname_override: CT3
role: [controlplane, worker, etcd]
- address: 192.168.0.204
#- address: [fd15:4ba5:5a2b:1008:20c:29ff:fe31:22ea]
user: rke
role: [controlplane, worker, etcd]
hostname_override: CT4
services:
etcd:
# 开启自动备份
## rke版本大于等于0.2.x或rancher版本大于等于v2.2.0时使用
backup_config:
enabled: true # 设置true启用ETCD自动备份,设置false禁用;
interval_hours: 12 # 快照创建间隔时间,不加此参数,默认5分钟;
retention: 6 # etcd备份保留份数;
# 修改空间配额为$((6*1024*1024*1024)),默认2G,最大8G
extra_args:
quota-backend-bytes: "6442450944"
auto-compaction-retention: 240 #(单位小时)
kube-api:
extra_args:
event-ttl: "48h" # 设置为您希望保留事件的持续时间
#Dual-stack ipv4/ipv6 set
service_cluster_ip_range: 10.43.0.0/16,fd98::/108
kubelet:
#挂载额外目录到kubelet容器
#extra_binds:
# - "/mnt:/mnt"
# 扩展变量
extra_args:
# 与 apiserver 会话时的并发数,默认是 10
kube-api-burst: '30'
# 与 apiserver 会话时的 QPS,默认是 5
kube-api-qps: '15'
# 修改节点最大 Pod 数量
#max-pods: '250'
# secrets 和 configmaps 同步到 Pod 需要的时间,默认一分钟
sync-frequency: '3s'
# kubelet 默认一次拉取一个镜像,设置为 false 可以同时拉取多个镜像,前提是存储驱动要为 overlay2,对应的 Docker 也需要增加下载并发数
serialize-image-pulls: false
# 拉取镜像的最大并发数,registry-burst 不能超过 registry-qps ,仅当 registry-qps 大于 0(零)时生效,(默认 10)。如果 registry-qps 为 0 则不限制(默认 5)。
registry-burst: '10'
registry-qps: '0'
# 以下配置用于配置节点资源预留和限制
cgroups-per-qos: 'true'
#cgroup-driver: cgroupfs (推荐systemd,docker已配置)
# 以下两个参数指明为相关服务预留多少资源,仅用于调度,不做实际限制
system-reserved: 'memory=300Mi'
kube-reserved: 'memory=2Gi'
enforce-node-allocatable: 'pods'
# 硬驱逐阈值,当节点上的可用资源少于这个值时,就会触发强制驱逐。强制驱逐会强制 kill 掉 POD,不会等 POD 自动退出。
#eviction-hard: 'memory.available<300Mi,nodefs.available<10%,imagefs.available<15%,nodefs.inodesFree<5%'
#按剩余空间
eviction-hard: 'memory.available<500Mi,nodefs.available<0.01Ki,imagefs.available<0.01Ki,nodefs.inodesFree<0.01Ki'
image-gc-high-threshold: '100'
kube-controller:
extra_args:
tls-cipher-suites: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384
##Dual-stack ipv4/ipv6 set
service_cluster_ip_range: 10.43.0.0/16,fd98::/108
cluster_cidr: 10.42.0.0/16,fd01::/64
scheduler:
extra_args:
tls-cipher-suites: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384
#Dual-stack ipv4/ipv6 set
network:
plugin: calico
# 当使用外部 TLS 终止,并且使用 ingress-nginx v0.22或以上版本时,必须。
ingress:
provider: nginx
options:
use-forwarded-headers: "true"
private_registries:
- url: registry.cn-hangzhou.aliyuncs.com
is_default: true # 所有的系统镜像都将使用该注册表进行拉取
# user: Username # 请替换为真实的用户名
# password: password # 请替换为真实的密码
启动集群
rke up --config rancher-cluster.yml
复制集群config文件为~/.kube/config,查看集群节点信息( 可通过–kubeconfig 指定config)
[rke@CT2 ~]$ mkdir ~/.kube
[rke@CT2 ~]$ cp kube_config_rancher-cluster.yml ~/.kube/config
[rke@CT2 ~]$ kubectl get node
NAME STATUS ROLES AGE VERSION
ct2 Ready controlplane,etcd,worker 62m v1.27.6
ct3 Ready controlplane,etcd,worker 62m v1.27.6
ct4 Ready controlplane,etcd,worker 62m v1.27.6
访问验证
部署nginx服务
采用三副本部署,可验证pod之间网络访问通信,跨节点访问通信
Service中 ipFamilyPolicy参数说明
这个字段指定了服务期望的IP地址族配置,它有三个可能的值:SingleStack、PreferDualStack和RequireDualStack。
SingleStack: 服务将只使用一个IP地址族,IPv4或IPv6,取决于集群配置。
PreferDualStack: 如果可能,服务将尝试使用两种IP地址族。如果集群不支持Dual-stack,那么服务将退回到单一IP地址族。
RequireDualStack: 服务将要求使用两种IP地址族。如果集群不支持Dual-stack,服务创建将失败。
vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
labels:
app: nginx
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.25.3-alpine
name: nginx
imagePullPolicy: IfNotPresent
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels:
service: nginx
topologyKey: kubernetes.io/hostname
weight: 100
---
apiVersion: v1
kind: Service
metadata:
namespace: default
labels:
app: nginx
name: nginx
spec:
ports:
- name: "80"
port: 80
targetPort: 80
nodePort: 30634
protocol: TCP
selector:
app: nginx
type: NodePort
# type: ClusterIP
# ipv6 set
ipFamilyPolicy: PreferDualStack
# ipFamilies: set priority
# - IPv4
# - IPv6
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "1800"
nginx.ingress.kubernetes.io/proxy-read-timeout: "1800"
nginx.ingress.kubernetes.io/proxy-body-size: 500g
nginx.ingress.kubernetes.io/server-snippet: client_header_buffer_size 2m;
name: nginx-ingress
namespace: default
spec:
rules:
#- host: aa.com
- host:
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
应用生效
kubectl apply -f nginx-deployment.yaml
查看pod
kubectl get pod -owide
[rke@CT2 ~]$ kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-5df577bf7c-4ftkt 1/1 Running 0 3m50s 10.42.121.132 ct3 <none> <none>
nginx-5df577bf7c-gqjmw 1/1 Running 0 3m50s 10.42.172.67 ct4 <none> <none>
nginx-5df577bf7c-xb4k4 1/1 Running 0 3m50s 10.42.223.134 ct2 <none> <none>
查看pod信息
可以看到pod 已分配ipv6地址
kubectl describe pod nginx-5df577bf7c-4ftkt
kubectl describe pod nginx-5df577bf7c-gqjmw
kubectl describe pod nginx-5df577bf7c-xb4k4
pod ip访问
分别访问Pod的IPv4与IPv6地址
IPv4地址
curl 10.42.121.132
curl 10.42.172.67
curl 10.42.223.134
IPv6地址
IPv6地址访问,需将地址用[]
括起来访问
curl [fd01::9dec:3f9f:ac1:6b83]
出现这个错误是因为curl默认启用了globbing特性,该特性允许你在URL中使用类似于shell的模式匹配(例如星号*)。在这种情况下,方括号[]可能被误解为globbing模式的一部分,从而导致错误。
为了解决这个问题,你可以尝试关闭curl的globbing特性。使用-g或–globoff选项来关闭globbing
curl -g [fd01::9dec:3f9f:ac1:6b83]
curl -g [fd01::ace4:ffe:9f84:b7c2]
curl -g [fd01::5f64:3f0e:18c1:a085]
pod 之间访问:
登录其中一个pod
kubectl exec -it nginx-5df577bf7c-4ftkt bash
IPv4地址:
curl 10.42.172.67
curl 10.42.223.134
IPv6地址:
curl -g [fd01::ace4:ffe:9f84:b7c2]
curl -g [fd01::5f64:3f0e:18c1:a085]
SVC访问
查看svc地址
kubectl get svc
kubectl describe svc nginx
访问svc地址:
IPv4地址:
curl 10.43.62.46
IPv6地址:
curl -g [fd98::1e68]
NodePort访问
IPv4地址:
curl 192.168.0.202:30634
curl 192.168.0.203:30634
curl 192.168.0.204:30634
IPv6访问:
curl -g [fd15:4ba5:5a2b:1008:20c:29ff:fef0:7e45]:30634
curl -g [fd15:4ba5:5a2b:1008:20c:29ff:fedc:24c7]:30634
curl -g [fd15:4ba5:5a2b:1008:20c:29ff:fe31:22ea]:30634
ingress访问
查看ingress
[rke@CT2 ~]$ kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-ingress nginx * 192.168.0.202,192.168.0.203,192.168.0.204 80 25m
由于未定义host中域名,可通过节点ip进行访问:
IPv4地址:
curl 192.168.0.202
curl 192.168.0.203
curl 192.168.0.204
IPv6访问:
curl -g [fd15:4ba5:5a2b:1008:20c:29ff:fef0:7e45]
curl -g [fd15:4ba5:5a2b:1008:20c:29ff:fedc:24c7]
curl -g [fd15:4ba5:5a2b:1008:20c:29ff:fe31:22ea]
浏览器访问:
IPv4访问:
IPv6访问:
FAQ
1、rke配置文件中节点 address使用IPv6地址报错
2、rke使用不指定网络插件报错,当前版本默认canal不支持IPv6
3、rancher使用ipv6地址访问,导入集群ipv6地址报错
[rke@CT2 ~]$ curl --insecure -sfL https://[fd15:4ba5:5a2b:1008:20c:29ff:fef0:7e45]:10443/v3/import/6m9z5t4mfrqdkknjcj6452wps9htvppfmhdwmcr7b6gcs48nzlmmgp_c-m-bfs25794.yaml | kubectl apply -f -
error: no objects passed to apply