天天看點

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 安裝虛拟網卡,參考這篇文章:CentOS 7 Tunctl 安裝 虛拟網卡_tom.ma的部落格-CSDN部落格_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 節點的改動如下圖所示

kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

修改之後執行 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 節點執行

kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

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           

修改後如下圖所示

kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

(二)安裝網絡插件 Flannel

1.目前叢集狀态

kubectl get pods -n kube-system
kubectl get nodes           
kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

可以看到,兩個 coredns 還是 Pending 狀态,此時還缺少網絡插件

2.安裝 Flannel 網絡插件

Kubernetes 為了讓網絡功能更加靈活,制定了 CNI 規範,由第三方實作網絡的細節功能。目前有多種網絡插件可供選擇,使用較多的是 Calico 和 Flannel,其他的網絡插件參考官方文檔:https://kubernetes.io/docs/concepts/cluster-administration/addons/

由于公網環境使用 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           

修改後的配置如下

kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

執行安裝指令

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 個從節點都加入叢集後,叢集狀态如下

kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

可以看到,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           
kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

w1 節點的公網 IP 為 1.116.156.102,w2 節點的公網 IP 為 121.37.169.103,NodePort 對外暴露的端口為 30992,通路結果如下

kubeadm + Flannel 基于公網 IP 搭建 K8s 叢集

測試通過,K8s 叢集搭建成功

七、參考文檔

CentOS 7 Tunctl 安裝虛拟網卡

選擇 Kubernetes 網絡插件

公網環境搭建 K8s 叢集

繼續閱讀