基于 Devbox 搭建 IPv4/IPv6 双协议栈 Kubernetes 集群实践

前言

Kubernetes 是当下热门的容器编排系统,在 Devbox 上搭建 Kubernetes 集群是一种较为便捷的学习方式。目前网上资料以搭建 IPv4 集群为主,在公司大力推进 IPv6 改造的当下,本文提供了双协议栈集群的一种搭建方式。

通过本文你可以:

  • 快速搭建一个双协议栈 K8s 集群

  • 创建一个支持双协议栈的 Web 服务

准备工作

整个搭建过程均在 root 角色下进行的。

配置

本文使用的环境配置,可以作为参考。

两台开发机一台Master节点,一台工作节点 Debian 10系统8核16G
containerd 版本v1.6.8
K8s 版本v1.25
Flannel 版本v0.19.2
swap swap 会导致集群无法启动,建议永久关闭 sed -i '/swap/s/^/#/' /etc/fstab

安装 containerd

可参考官方安装指令:Install Docker Engine on Debian

Shell 复制代码
apt-get update
apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release \
    apt-transport-https
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

因为 containerd 默认镜像拉取地址为国外仓库下载速度较慢,可能会报错"net/http: TLS handshake timeout",可以安装镜像加速器。在 /etc/docker/daemon.json 文件括号内添加下面的值。

Shell 复制代码
{
  "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"]
}

保存修改后重启 containerd 使配置生效。

Shell 复制代码
# 守护进程重启
systemctl daemon-reload
# 重启containerd服务
systemctl restart containerd

安装 K8s

从 1.21 版本开始,K8s 集群默认启用 IPv4/IPv6 双协议栈网络,以支持同时分配 IPv4 和 IPv6 地址。而官网建议使用 v1.23 版本之后的,这里选择安装了 K8s 的最新版本 v1.25 。

Shell 复制代码
apt-get update
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update -y
apt-get install -y kubelet kubeadm kubectl

搭建集群

启动 Master 节点

Shell 复制代码
kubeadm init --pod-network-cidr=10.244.0.0/16,2001:db8:42:0::/56 --service-cidr=10.96.0.0/16,2001:db8:42:1::/112 --image-repository=registry.aliyuncs.com/google_containers --ignore-preflight-errors=all

初始化成功后会返回下面内容,保存一下,这个命令用于其他节点加入到集群中,而且 Token 是有时效性的,过期时间一般是1天。

Shell 复制代码
kubeadm join *** --token *** \
        --discovery-token-ca-cert-hash ***

如果忘了保存,可以执行下面指令查看。

Shell 复制代码
kubeadm token create --print-join-command

安装网络通信插件

初始化集群后, Master 节点处于 Not-ready 的状态,需要安装网络通信插件,这里使用 Flannel 进行演示。从 kube-flannel.yml获取网页内容到本地,并在 ConfigMap.data.net-conf.json 字段新增"EnableIPv6"和"IPv6Network"表示支持双栈。

接着执行下面命令安装 Flannel 插件。

Shell 复制代码
kubectl apply -f kube-flannel.yml

可执行下面命令查看安装结果。

Shell 复制代码
cat /run/flannel/subnet.env

如图所示,新增了两个字段:

  • FLANNEL_IPV6_NETWORK

  • FLANNEL_IPV6_SUBNET

工作节点加入集群

首先在工作节点上根据以上步骤安装好 containerd 和 K8s 。执行以下命令,将工作节点加入到 Master 节点的集群中。

Shell 复制代码
kubeadm join *** --token *** \
        --discovery-token-ca-cert-hash ***

如下表示加入集群成功。

等待节点创建成功,分别执行以下命令查看 nodes 和 pods 状态。

Shell 复制代码
kubectl get nodes
kubectl get pod -A -o wide 

验证 IPv4 /IPv6 双****协议栈

验证寻址

每个双协议栈节点应分配一个 IPv4 块和一个 IPv6 块。 通过运行以下命令来验证是否配置了 IPv4/IPv6 Pod 地址范围。 将示例节点名称替换为集群中的有效双协议栈节点。 在此示例中,节点的名称为 n248-173-091。

Shell 复制代码
 kubectl get nodes n248-173-091 -o go-template --template='{{range .spec.podCIDRs}}{{printf "%s\n" .}}{{end}}'
Shell 复制代码
10.244.1.0/24
2001:db8:42:2::/64

验证服务支持双栈

下面通过创建一个 Nginx 服务验证双协议栈生效。

  1. 创建 nginx 的发布 deployment , K8s 通过 deployment 来部署应用

创建 nginx-dep.yml 文件并执行以下命令。

Shell 复制代码
kubectl apply -f nginx-dep.yml
YAML 复制代码
# nginx-dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80

执行以下命令查看 deployment 状态,可以看到3个 pod 均处于READY状态。

Shell 复制代码
kubectl get deploy -o wide
Shell 复制代码
NAME               READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES         SELECTOR
nginx-deployment   3/3     3            3           2d17h   nginx        nginx:alpine   app=nginx
  1. 创建 nginx 的服务 Service , K8s 使用 Service 来实现服务发现

创建 nginx-svc.yml 文件,执行以下命令。

Shell 复制代码
kubectl apply -f nginx-svc.yml
YAML 复制代码
# nginx-svc.yml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ipFamilyPolicy: PreferDualStack 
  ipFamilies: 
  - IPv6
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

其中.spec.ipFamilyPolicy可设置为PreferDualStack或RequireDualStack以激活双栈支持,默认为SingleStack。

.spec.ipFamilies字段用来设置 IPv4 和 IPv6 的首选项顺序。

执行以下命令查看 Service 状态。

Shell 复制代码
kubectl get svc nginx-service -o wide

为了验证在外部正常访问 nginx,打开浏览器,输入工作节点的 ip+port ,可以看到 nginx 的欢迎页面,说明 nginx-service 创建成功。

常见问题

以下是我在搭建过程中遇到的一些问题,仅供参考。

  1. 当执行集群初始化命令时,出现 timed out waiting for the condition 的报错

执行journalctl -xeu kubelet查询日志,检查是不是 pause 镜像没有下载成功,因为阿里的kubernetes仓库虽然可以下载到 K8s v1.23+以上的镜像,但是有一个问题,其pause容器还是用的k8s.gcr.io/pause:3.6,该镜像在国内服务器下载不成功,需要手工下载。

Shell 复制代码
# 由于k8s.gcr.io 需要连外网才可以拉取到,导致 k8s 的基础容器 pause 经常无法获取。k8s docker 可使用代理服拉取,再利用 docker tag 解决问题
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6 k8s.gcr.io/pause:3.6

# 但是我们k8s集群中使用的CRI是containerd。所以只能通过 docker tag 镜像,再使用 ctr 导入镜像.
docker save k8s.gcr.io/pause -o pause.tar
ctr -n k8s.io images import pause.tar

# 重启
systemctl restart containerd
kubeadm reset

# 重新执行初始化命令
kubeadm init --pod-network-cidr=10.244.0.0/16,2001:db8:42:0::/56 --service-cidr=10.96.0.0/16,2001:db8:42:1::/112 --image-repository=registry.aliyuncs.com/google_containers --ignore-preflight-errors=all
  1. 当节点加入master后报错:Config not found: /etc/kubernetes/admin.conf

在工作节点的 /etc/kubernetes/ 位置创建 admin.conf ,把 master 节点的 admin.conf 内容复制进去,再新增环境变量。

Shell 复制代码
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile
  1. pod****中的coredns 一直重启

执行kubeadm reset 重置,并执行ifconfig,cni0 的IP地址段不属于 Flannel 的IP地址段里,需要清理一下网络,删除 cni0 ,之后会自动重建。

Shell 复制代码
ifconfig cni0 down    
ip link delete cni0

如果网卡 cni0 删除后没有重建时,重启 containerd 。

Shell 复制代码
systemctl daemon-reload
systemctl restart containerd

总结

本文演示了如何在 Devbox 上搭建一个双协议栈 Kubernetes 集群,并通过部署一个 Nginx 服务进行了验证。未来会提供更多实践类的文章,比如基于 Devbox 搭建一个高可用的 Kubernetes 集群。

参考资料

相关推荐
moton20171 小时前
云原生:构建现代化应用的基石
后端·docker·微服务·云原生·容器·架构·kubernetes
xiao-xiang4 小时前
jenkins-k8s pod方式动态生成slave节点
java·kubernetes·jenkins
QQ_7781329746 小时前
在K8S中使用Values文件定制不同环境下的应用配置详解
kubernetes
元气满满的热码式21 小时前
K8S中Service详解(三)
云原生·容器·kubernetes
周杰伦_Jay1 天前
详细介绍:Kubernetes(K8s)的技术架构(核心概念、调度和资源管理、安全性、持续集成与持续部署、网络和服务发现)
网络·ci/cd·架构·kubernetes·服务发现·ai编程
周杰伦_Jay1 天前
详细介绍:云原生技术细节(关键组成部分、优势和挑战、常用云原生工具)
java·云原生·容器·架构·kubernetes·jenkins·devops
元气满满的热码式1 天前
K8S中Pod控制器之DaemonSet(DS)控制器
云原生·容器·kubernetes
夏子曦1 天前
k8s 蓝绿发布、滚动发布、灰度发布
云原生·容器·kubernetes
颜淡慕潇1 天前
【K8S系列】在 K8S 中使用 Values 文件定制不同环境下的应用配置
云原生·容器·kubernetes·环境配置
旦沐已成舟1 天前
K8S-Pod的环境变量,重启策略,数据持久化,资源限制
java·docker·kubernetes