kubeadm + Flannel 基于公网 IP 搭建 K8s 集群

CentOS 7.6 系统主机 3 台,基于公网 IP 搭建 1 主 2 从的 Kubernetes 集群 

一、准备工作

1.版本信息

Docker 20.10.21
Kubernetes 1.21.0-0
Flannel 0.20.2

2.集群角色规划

3 台 CentOS 7.6 主机,集群角色规划如下

Master Worker01 Worker02
公网 IP 139.196.219.92 1.116.156.102 121.37.169.103
内网 IP 172.21.253.164 10.0.4.15 192.168.0.89
服务器厂商 阿里云 腾讯云 华为云

3.修改 hosts 文件

设置 master 主机的 hostname 为 m

sudo hostnamectl set-hostname m

分别设置 2 台 worker 主机的 hostname

sudo hostnamectl set-hostname w1 
sudo hostnamectl set-hostname w2

分别修改 3 台主机的 hosts 文件,这里配置的是公网 IP。因为云服务器厂商不同,无法搭建局域网 K8s 集群

vim /etc/hosts
 
139.196.219.92 m 
1.116.156.102 w1 
121.37.169.103 w2

4.创建虚拟网卡

3 台主机分别填写对应的公网 IP

# 打开文件
vim /etc/sysconfig/network-scripts/ifcfg-eth0:1

# 填入内容
NAME=eth0:1
DEVICE=eth0:1
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
NETMASK=255.255.255.0
IPADDR=<public ip>

# 重启网络
systemctl restart network.service

创建虚拟网卡前,查看 eth0

[root@w1 network-scripts]# ip a | grep eth0

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 10.0.4.15/22 brd 10.0.7.255 scope global eth0

创建虚拟网卡后,查看 eth0,可以发现多了一条记录 eth0:1

[root@w1 ~]# ip a | grep eth0

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 10.0.4.15/22 brd 10.0.7.255 scope global eth0
    inet 1.116.156.102/24 brd 1.116.156.255 scope global eth0:1

华为云主机通过上述方式添加虚拟网卡时失败,改为使用 Tunctl 安装虚拟网卡,参考这篇文章:链接

但需要注意的是,需要将这篇文章中的 tap0 改为 eth0:1,命名与其他主机保持一致

5.云服务器安全组设置

搭建 K8s 集群需要对云服务器安全组入方向规则进行配置,开启相应的端口

master 节点

协议 端口 作用 使用者
TCP 2379~2380 etcd 客户端 API kube-apiserver, etcd
TCP 6443 api-server API 所有组件
UDP 8472 VxLan Overlay 网络通信 Flannel 网络插件
TCP 10250 kubelet API kubelet, Control Plane 组件
TCP 10251 kube-scheduler kube-scheduler
TCP 10252 kube-controller-manager kube-controller-manager

worker 节点

协议 端口 作用 使用者
UDP 8472 VxLan Overlay 网络通信 Flannel 网络插件
TCP 10250 kubelet API kubelet, Control Plane 组件
TCP 30000~32767 NodePort 服务 所有组件

二、系统基础配置

1.更新并安装依赖 

准备好 3 台主机后,每台主机均需要更新并安装依赖

sudo yum -y update 
sudo yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp
sudo yum install -y yum-utils

2.基础配置

关闭防火墙

systemctl stop firewalld && systemctl disable firewalld

关闭 SELinux (Security Enhanced Linux)

setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

关闭 swap

swapoff -a
sed -i '/swap/s/^(.*)$/#\1/g' /etc/fstab

配置 iptables 的 ACCEPT 规则

iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT

设置系统参数

cat <<EOF> /etc/sysctl.d/k8s.conf 
net.bridge.bridge-nf-call-ip6tables = 1 
net.bridge.bridge-nf-call-iptables = 1 
EOF
sysctl --system

三、安装 Docker

1.配置阿里云镜像源

sudo yum-config-manager \
    --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 查看 Docker-CE
yum list | grep docker-ce

# 更新 yum 缓存
sudo yum makecache fast

2.安装 Docker

安装指定版本 20.10.21

sudo yum install -y docker-ce-20.10.21 docker-ce-cli-20.10.21 containerd.io

3.启动 Docker

# 启动 Docker
sudo systemctl start docker
# 设置开机启动 Docker
sudo systemctl enable docker

四、安装 Kubernetes 集群所需组件

(一) 安装 kubeadm, kubelete, kubectl

1.配置 yum 源

cat <<EOF> /etc/yum.repos.d/kubernetes.repo 
[kubernetes] 
name=Kubernetes 
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 
enabled=1 
gpgcheck=0 
repo_gpgcheck=0 
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg 
    http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg 
EOF

2.开始安装

# 确认 yum 中是否有指定版本
yum list kubeadm --showduplicates | sort -r

# 安装 1.21.0-0
yum install -y kubeadm-1.21.0-0 kubelet-1.21.0-0 kubectl-1.21.0-0

3.Docker 和 K8s 设置为同一个 cgroup

(1) 修改 daemon.json
vim /etc/docker/daemon.json
设置 cgroup
"exec-opts": ["native.cgroupdriver=systemd"]

(2) 重启 Docker
systemctl restart docker

(3) 检查 kubelet,如果在输出信息中发现 No such file or directory,说明没问题
sed -i "s/cgroup-driver=systemd/cgroup-driver=cgroupfs/g" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

4.修改 kubelet 启动参数

每台主机都要添加并指定对应的公网 IP,然后才能使用公网 IP 进行集群间通信

vim /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf

在 KUBELET_KUBECONFIG_ARGS 后面追加 --node-ip=<public_ip>

w2 节点的改动如下图所示

修改之后执行 daemon-reload 让修改生效

systemctl daemon-reload

5.启动 kubelet / 重启 kubelet

启动 kubelet

systemctl enable kubelet && systemctl start kubelet

重启 kubelet

systemctl restart kubelet

(二) 拉取 kube-proxy, scheduler 等镜像

需要通过国内镜像源下载镜像

1.查看 kubeadm 所需镜像

kubeadm config images list

输出信息如下

k8s.gcr.io/kube-apiserver:v1.21.14
k8s.gcr.io/kube-controller-manager:v1.21.14
k8s.gcr.io/kube-scheduler:v1.21.14
k8s.gcr.io/kube-proxy:v1.21.14
k8s.gcr.io/pause:3.4.1
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns/coredns:v1.8.0

遗憾的是需要科学上网才能下载这些镜像

2.尝试用国内镜像源拉取镜像

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.21.14

经过测试,可以正常拉取,因此编写一个 Shell 脚本,通过国内镜像源拉取 kubeadm 所需镜像

切换到一个目录,编写 kubeadm_image.sh,用于从阿里云镜像源拉取镜像 / 重新打 tag / 删除原镜像

#!/usr/bin/env bash

# 镜像处理过程中,如果遇到错误,立即退出
set -e

# 版本定义
readonly KUBE_VERSION=v1.21.0
readonly PAUSE_VERSION=3.4.1
readonly ETCD_VERSION=3.4.13-0
readonly CORE_DNS_VERSION=v1.8.0
readonly OFFICIAL_URL=k8s.gcr.io
readonly ALIYUN_URL=registry.cn-hangzhou.aliyuncs.com/google_containers

# 镜像列表
imageList=(kube-apiserver:${KUBE_VERSION} 
kube-controller-manager:${KUBE_VERSION} 
kube-scheduler:${KUBE_VERSION} 
kube-proxy:${KUBE_VERSION} 
pause:${PAUSE_VERSION} 
etcd:${ETCD_VERSION} 
coredns:${CORE_DNS_VERSION})

# 镜像转换操作
for imageItem in ${imageList[@]} ; do 
  # 从国内镜像源拉取镜像
  docker pull $ALIYUN_URL/$imageItem
  # 给镜像重新打一个标签,命名为 kubeadm 所需的镜像
  docker tag $ALIYUN_URL/$imageItem $OFFICIAL_URL/$imageItem
  # 删除原有镜像
  docker rmi $ALIYUN_URL/$imageItem
done

# coredns 的镜像比较特殊,单独处理
docker tag ${OFFICIAL_URL}/coredns:${CORE_DNS_VERSION} ${OFFICIAL_URL}/coredns/coredns:${CORE_DNS_VERSION}
docker rmi ${OFFICIAL_URL}/coredns:${CORE_DNS_VERSION}

运行脚本

sh ./kubeadm_image.sh

五、搭建 Kubernetes 集群

(一)用 kubeadm 初始化 master 节点

1.执行 kubeadm init

kubeadm init --kubernetes-version=1.21.0 \
  --apiserver-advertise-address=139.196.219.92 \
  --pod-network-cidr=10.244.0.0/16 \
  -v=5

输出日志中出现如下信息时,说明 master 节点已经初始化成功了

Your Kubernetes control-plane has initialized successfully!

将末尾的 kubeadm join 信息保存起来,后面的步骤中需要在 worker 节点执行

2.集群健康检查

执行如下命令

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

集群健康检查

# 检查集群状态
kubectl cluster-info

# 健康检查
curl -k https://localhost:6443/healthz

 3.修改kube-apiserver 配置

kube-apiserver 添加 --bind-address=0.0.0.0,确认 --advertise-addres=<公网 IP>

vim /etc/kubernetes/manifests/kube-apiserver.yaml

修改后如下图所示

(二)安装网络插件 Flannel

1.当前集群状态

kubectl get pods -n kube-system
kubectl get nodes

可以看到,两个 coredns 还是 Pending 状态,此时还缺少网络插件

2.安装 Flannel 网络插件

Kubernetes 为了让网络功能更加灵活,制定了 CNI 规范,由第三方实现网络的细节功能。目前有多种网络插件可供选择,使用较多的是 Calico 和 Flannel,其他的网络插件参考官方文档:链接

由于公网环境使用 Calico 网络插件配置比较复杂,也没有调试成功,因此本文使用 Flannel 网络插件,安装命令如下,在 master 节点执行

# 进入一个目录,假设为 /var/local/k8s
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

修改 kube-flannel.yml,新增 2 个配置

vim kube-flannel.yml

第 1 处

containers:
- name: kube-flannel
  #image: flannelcni/flannel:v0.20.2 #for ppc64le and mips64le (dockerhub limitations may apply)
  image: docker.io/rancher/mirrored-flannelcni-flannel:v0.20.2
  command:
  - /opt/bin/flanneld
  args:
  - --public-ip=$(PUBLIC_IP)
  - --iface=eth0
  - --ip-masq
  - --kube-subnet-mgr

第 2 处

env:
- name: PUBLIC_IP
  valueFrom:
    fieldRef:
      fieldPath: status.podIP

修改后的配置如下

执行安装命令

kubectl apply -f kube-flannel.yml

(三)用 kubeadm 将从节点加入集群

执行如下命令,将 worker 节点加入集群

kubeadm join 139.196.219.92:6443 --token o0zxc6.fmmh2sn8wlbt9onm \
  --discovery-token-ca-cert-hash sha256:a52cec58178c402ecaecc74375d49495c1bf13661dd0b25b158e7caf5d619fa6 \
  -v=5

输出日志中出现如下信息时,说明 worker 节点已经成功加入集群

This node has joined the cluster

将 2 个从节点都加入集群后,集群状态如下

可以看到,3 个节点都处于可用状态,3 个 Flannel pod 也是绑定的公网 IP

六、自定义 Pod 测试

pod-nginx.yml

apiVersion: apps/v1 
kind: ReplicaSet 
metadata: 
  name: my-nginx 
  labels: 
    tier: frontend 
spec: 
  replicas: 6 
  selector: 
    matchLabels: 
      tier: frontend 
  template: 
    metadata: 
      name: my-nginx 
      labels: 
        tier: frontend 
    spec:
      containers: 
      - name: my-nginx 
        image: nginx 
        ports: 
        - containerPort: 80 
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx-service
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    nodePort: 30992
  selector:
    tier: frontend 

执行

# 切换到 pod-nginx.yml 所在目录
kubectl apply -f pod-nginx.yml

查看 my-nginx 对外暴露的端口

# 查看已暴露的端口
kubectl get services

w1 节点的公网 IP 为 1.116.156.102,w2 节点的公网 IP 为 121.37.169.103,NodePort 对外暴露的端口为 30992,访问结果如下

测试通过,K8s 集群搭建成功

七、参考文档

CentOS 7 Tunctl 安装虚拟网卡

选择 Kubernetes 网络插件

公网环境搭建 K8s 集群

猜你喜欢

转载自blog.csdn.net/u013481793/article/details/128433729