k8s系列02-kubeadm部署flannel網絡的k8s集群

本文主要在centos7系統上基于dockerflannel組件部署v1.23.6版本的k8s原生集群,由于集群主要用于自己平時學習和測試使用,加上資源有限,暫不涉及高可用部署。

此前寫的一些關于k8s基礎知識和集群搭建的一些方案,有需要的同學可以看一下。

1、準備工作

1.1 flannel-集群節點信息

機器均為8C8G的虛擬機,硬盤為100G。

IP Hostname
10.31.8.1 tiny-flannel-master-8-1.k8s.tcinternal
10.31.8.11 tiny-flannel-worker-8-11.k8s.tcinternal
10.31.8.12 tiny-flannel-worker-8-12.k8s.tcinternal
10.8.64.0/18 podSubnet
10.8.0.0/18 serviceSubnet

1.2 檢查mac和product_uuid

同一個k8s集群內的所有節點需要確保mac地址和product_uuid均唯一,開始集群初始化之前需要檢查相關信息

# 檢查mac地址
ip link 
ifconfig -a

# 檢查product_uuid
sudo cat /sys/class/dmi/id/product_uuid

1.3 配置ssh免密登錄(可選)

如果k8s集群的節點有多個網卡,確保每個節點能通過正確的網卡互聯訪問

# 在root用戶下面生成一個公用的key,并配置可以使用該key免密登錄
su root
ssh-keygen
cd /root/.ssh/
cat id_rsa.pub >> authorized_keys
chmod 600 authorized_keys


cat >> ~/.ssh/config <<EOF
Host tiny-flannel-master-8-1.k8s.tcinternal
    HostName 10.31.8.1
    User root
    Port 22
    IdentityFile ~/.ssh/id_rsa

Host tiny-flannel-worker-8-11.k8s.tcinternal
    HostName 10.31.8.11
    User root
    Port 22
    IdentityFile ~/.ssh/id_rsa

Host tiny-flannel-worker-8-12.k8s.tcinternal
    HostName 10.31.8.12
    User root
    Port 22
    IdentityFile ~/.ssh/id_rsa
EOF

1.4 修改hosts文件

cat >> /etc/hosts <<EOF
10.31.8.1  tiny-flannel-master-8-1 tiny-flannel-master-8-1.k8s.tcinternal
10.31.8.11 tiny-flannel-worker-8-11 tiny-flannel-worker-8-11.k8s.tcinternal
10.31.8.12 tiny-flannel-worker-8-12 tiny-flannel-worker-8-12.k8s.tcinternal
EOF

1.5 關閉swap內存

# 使用命令直接關閉swap內存
swapoff -a
# 修改fstab文件禁止開機自動掛載swap分區
sed -i '/swap / s/^\(.*\)$/#\1/g' /etc/fstab

1.6 配置時間同步

這里可以根據自己的習慣選擇ntp或者是chrony同步均可,同步的時間源服務器可以選擇阿里云的ntp1.aliyun.com或者是國家時間中心的ntp.ntsc.ac.cn

使用ntp同步

# 使用yum安裝ntpdate工具
yum install ntpdate -y

# 使用國家時間中心的源同步時間
ntpdate ntp.ntsc.ac.cn

# 最后查看一下時間
hwclock

使用chrony同步

# 使用yum安裝chrony
yum install chrony -y

# 設置開機啟動并開啟chony并查看運行狀態
systemctl enable chronyd.service
systemctl start chronyd.service
systemctl status chronyd.service

# 當然也可以自定義時間服務器
vim /etc/chrony.conf

# 修改前
$ grep server /etc/chrony.conf
# Use public servers from the pool.ntp.org project.
server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst

# 修改后
$ grep server /etc/chrony.conf
# Use public servers from the pool.ntp.org project.
server ntp.ntsc.ac.cn iburst

# 重啟服務使配置文件生效
systemctl restart chronyd.service

# 查看chrony的ntp服務器狀態
chronyc sourcestats -v
chronyc sources -v

1.7 關閉selinux

# 使用命令直接關閉
setenforce 0

# 也可以直接修改/etc/selinux/config文件
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config

1.8 配置防火墻

k8s集群之間通信和服務暴露需要使用較多端口,為了方便,直接禁用防火墻

# centos7使用systemctl禁用默認的firewalld服務
systemctl disable firewalld.service

1.9 配置netfilter參數

這里主要是需要配置內核加載br_netfilteriptables放行ipv6ipv4的流量,確保集群內的容器能夠正常通信。

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

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

1.10 關閉IPV6(可選)

雖然新版本的k8s已經支持雙棧網絡,但是本次的集群部署過程并不涉及IPv6網絡的通信,因此關閉IPv6網絡支持

# 直接在內核中添加ipv6禁用參數
grubby --update-kernel=ALL --args=ipv6.disable=1

1.11 配置IPVS(可選)

IPVS是專門設計用來應對負載均衡場景的組件,kube-proxy 中的 IPVS 實現通過減少對 iptables 的使用來增加可擴展性。在 iptables 輸入鏈中不使用 PREROUTING,而是創建一個假的接口,叫做 kube-ipvs0,當k8s集群中的負載均衡配置變多的時候,IPVS能實現比iptables更高效的轉發性能。

注意在4.19之后的內核版本中使用nf_conntrack模塊來替換了原有的nf_conntrack_ipv4模塊

(Notes: use nf_conntrack instead of nf_conntrack_ipv4 for Linux kernel 4.19 and later)

# 在使用ipvs模式之前確保安裝了ipset和ipvsadm
sudo yum install ipset ipvsadm -y

# 手動加載ipvs相關模塊
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4

# 配置開機自動加載ipvs相關模塊
cat <<EOF | sudo tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack_ipv4
EOF

sudo sysctl --system
# 最好重啟一遍系統確定是否生效

$ lsmod | grep -e ip_vs -e nf_conntrack_ipv4
ip_vs_sh               12688  0
ip_vs_wrr              12697  0
ip_vs_rr               12600  0
ip_vs                 145458  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack_ipv4      15053  2
nf_defrag_ipv4         12729  1 nf_conntrack_ipv4
nf_conntrack          139264  7 ip_vs,nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4
libcrc32c              12644  4 xfs,ip_vs,nf_nat,nf_conntrack
$ cut -f1 -d " "  /proc/modules | grep -e ip_vs -e nf_conntrack_ipv4
ip_vs_sh
ip_vs_wrr
ip_vs_rr
ip_vs
nf_conntrack_ipv4

2、安裝container runtime

2.1 安裝docker

詳細的官方文檔可以參考這里,由于在剛發布的1.24版本中移除了docker-shim,因此安裝的版本≥1.24的時候需要注意容器運行時的選擇。這里我們安裝的版本低于1.24,因此我們繼續使用docker。

docker的具體安裝可以參考我之前寫的這篇文章,這里不做贅述。

# 安裝必要的依賴組件并且導入docker官方提供的yum源
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo  https://download.docker.com/linux/centos/docker-ce.repo

# 我們直接安裝最新版本的docker
yum install docker-ce docker-ce-cli containerd.io

2.2 配置cgroup drivers

CentOS7使用的是systemd來初始化系統并管理進程,初始化進程會生成并使用一個 root 控制組 (cgroup), 并充當 cgroup 管理器。 Systemdcgroup 集成緊密,并將為每個 systemd 單元分配一個 cgroup。 我們也可以配置容器運行時kubelet 使用 cgroupfs。 連同 systemd 一起使用 cgroupfs 意味著將有兩個不同的 cgroup 管理器。而當一個系統中同時存在cgroupfs和systemd兩者時,容易變得不穩定,因此最好更改設置,令容器運行時和 kubelet 使用 systemd 作為 cgroup 驅動,以此使系統更為穩定。 對于 Docker, 需要設置 native.cgroupdriver=systemd 參數。

參考官方的說明文檔:

https://kubernetes.io/docs/setup/production-environment/container-runtimes/#cgroup-drivers

參考配置說明文檔

https://kubernetes.io/zh/docs/setup/production-environment/container-runtimes/#docker

sudo mkdir /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker


# 最后檢查一下Cgroup Driver是否為systemd
$ docker info | grep systemd
 Cgroup Driver: systemd

2.3 關于kubelet的cgroup driver

k8s官方有詳細的文檔介紹了如何設置kubelet的cgroup driver,需要特別注意的是,在1.22版本開始,如果沒有手動設置kubelet的cgroup driver,那么默認會設置為systemd

Note: In v1.22, if the user is not setting the cgroupDriver field under KubeletConfiguration, kubeadm will default it to systemd.

一個比較簡單的指定kubelet的cgroup driver的方法就是在kubeadm-config.yaml加入cgroupDriver字段

# kubeadm-config.yaml
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.21.0
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

我們可以直接查看configmaps來查看初始化之后集群的kubeadm-config配置。

$ kubectl describe configmaps kubeadm-config -n kube-system
Name:         kubeadm-config
Namespace:    kube-system
Labels:       <none>
Annotations:  <none>

Data
====
ClusterConfiguration:
----
apiServer:
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.23.6
networking:
  dnsDomain: cali-cluster.tclocal
  serviceSubnet: 10.88.0.0/18
scheduler: {}


BinaryData
====

Events:  <none>

當然因為我們需要安裝的版本高于1.22.0并且使用的就是systemd,因此可以不用再重復配置。

3、安裝kube三件套

對應的官方文檔可以參考這里

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl

kube三件套就是kubeadmkubeletkubectl,三者的具體功能和作用如下:

  • kubeadm:用來初始化集群的指令。
  • kubelet:在集群中的每個節點上用來啟動 Pod 和容器等。
  • kubectl:用來與集群通信的命令行工具。

需要注意的是:

  • kubeadm不會幫助我們管理kubeletkubectl,其他兩者也是一樣的,也就是說這三者是相互獨立的,并不存在誰管理誰的情況;
  • kubelet的版本必須小于等于API-server的版本,否則容易出現兼容性的問題;
  • kubectl并不是集群中的每個節點都需要安裝,也并不是一定要安裝在集群中的節點,可以單獨安裝在自己本地的機器環境上面,然后配合kubeconfig文件即可使用kubectl命令來遠程管理對應的k8s集群;

CentOS7的安裝比較簡單,我們直接使用官方提供的yum源即可。需要注意的是這里需要設置selinux的狀態,但是前面我們已經關閉了selinux,因此這里略過這步。

# 直接導入谷歌官方的yum源
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

# 當然如果連不上谷歌的源,可以考慮使用國內的阿里鏡像源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF


# 接下來直接安裝三件套即可
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

# 如果網絡環境不好出現gpgcheck驗證失敗導致無法正常讀取yum源,可以考慮關閉該yum源的repo_gpgcheck
sed -i 's/repo_gpgcheck=1/repo_gpgcheck=0/g' /etc/yum.repos.d/kubernetes.repo
# 或者在安裝的時候禁用gpgcheck
sudo yum install -y kubelet kubeadm kubectl --nogpgcheck --disableexcludes=kubernetes



# 如果想要安裝特定版本,可以使用這個命令查看相關版本的信息
sudo yum list --nogpgcheck kubelet kubeadm kubectl --showduplicates --disableexcludes=kubernetes
# 這里我們為了保留使用docker-shim,因此我們按照1.24.0版本的前一個版本1.23.6
sudo yum install -y kubelet-1.23.6-0 kubeadm-1.23.6-0 kubectl-1.23.6-0 --nogpgcheck --disableexcludes=kubernetes

# 安裝完成后配置開機自啟kubelet
sudo systemctl enable --now kubelet

4、初始化集群

4.1 編寫配置文件

在集群中所有節點都執行完上面的三點操作之后,我們就可以開始創建k8s集群了。因為我們這次不涉及高可用部署,因此初始化的時候直接在我們的目標master節點上面操作即可。

# 我們先使用kubeadm命令查看一下主要的幾個鏡像版本
# 因為我們此前指定安裝了舊的1.23.6版本,這里的apiserver鏡像版本也會隨之回滾
$ kubeadm config images list
I0507 14:14:34.992275   20038 version.go:255] remote version is much newer: v1.24.0; falling back to: stable-1.23
k8s.gcr.io/kube-apiserver:v1.23.6
k8s.gcr.io/kube-controller-manager:v1.23.6
k8s.gcr.io/kube-scheduler:v1.23.6
k8s.gcr.io/kube-proxy:v1.23.6
k8s.gcr.io/pause:3.6
k8s.gcr.io/etcd:3.5.1-0
k8s.gcr.io/coredns/coredns:v1.8.6

# 為了方便編輯和管理,我們還是把初始化參數導出成配置文件
$ kubeadm config print init-defaults > kubeadm-flannel.conf

  • 考慮到大多數情況下國內的網絡無法使用谷歌的k8s.gcr.io鏡像源,我們可以直接在配置文件中修改imageRepository參數為阿里的鏡像源
  • kubernetesVersion字段用來指定我們要安裝的k8s版本
  • localAPIEndpoint參數需要修改為我們的master節點的IP和端口,初始化之后的k8s集群的apiserver地址就是這個
  • serviceSubnetdnsDomain兩個參數默認情況下可以不用修改,這里我按照自己的需求進行了變更
  • nodeRegistration里面的name參數修改為對應master節點的hostname
  • 新增配置塊使用ipvs,具體可以參考官方文檔
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 10.31.8.1
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  imagePullPolicy: IfNotPresent
  name: tiny-flannel-master-8-1.k8s.tcinternal
  taints: null
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.23.6
networking:
  dnsDomain: flan-cluster.tclocal
  serviceSubnet: 10.8.0.0/18
  podSubnet: 10.8.64.0/18
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

4.2 初始化集群

此時我們再查看對應的配置文件中的鏡像版本,就會發現已經變成了對應阿里云鏡像源的版本

# 查看一下對應的鏡像版本,確定配置文件是否生效
$ kubeadm config images list --config kubeadm-flannel.conf
registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.6
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.6
registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.6
registry.aliyuncs.com/google_containers/kube-proxy:v1.23.6
registry.aliyuncs.com/google_containers/pause:3.6
registry.aliyuncs.com/google_containers/etcd:3.5.1-0
registry.aliyuncs.com/google_containers/coredns:v1.8.6

# 確認沒問題之后我們直接拉取鏡像
$ kubeadm config images pull --config kubeadm-flannel.conf
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.6
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.6
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.6
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.23.6
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.6
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.5.1-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:v1.8.6

# 初始化
$ kubeadm init --config kubeadm-flannel.conf
[init] Using Kubernetes version: v1.23.6
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
...此處略去一堆輸出...

當我們看到下面這個輸出結果的時候,我們的集群就算是初始化成功了。

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.31.8.1:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:d7160866920c0331731ad3c1c31a6e5b6c788b5682f86971cacaa940211db9ab
        

4.3 配置kubeconfig

剛初始化成功之后,我們還沒辦法馬上查看k8s集群信息,需要配置kubeconfig相關參數才能正常使用kubectl連接apiserver讀取集群信息。

# 對于非root用戶,可以這樣操作
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 如果是root用戶,可以直接導入環境變量
export KUBECONFIG=/etc/kubernetes/admin.conf

# 添加kubectl的自動補全功能
echo "source <(kubectl completion bash)" >> ~/.bashrc

前面我們提到過kubectl不一定要安裝在集群內,實際上只要是任何一臺能連接到apiserver的機器上面都可以安裝kubectl并且根據步驟配置kubeconfig,就可以使用kubectl命令行來管理對應的k8s集群。

配置完成后,我們再執行相關命令就可以查看集群的信息了。

$ kubectl cluster-info
Kubernetes control plane is running at https://10.31.8.1:6443
CoreDNS is running at https://10.31.8.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ kubectl get nodes -o wide
NAME                                     STATUS     ROLES                  AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
tiny-flannel-master-8-1.k8s.tcinternal   NotReady   control-plane,master   79s   v1.23.6   10.31.8.1     <none>        CentOS Linux 7 (Core)   3.10.0-1160.62.1.el7.x86_64   docker://20.10.14

$ kubectl get pods -A -o wide
NAMESPACE     NAME                                                             READY   STATUS    RESTARTS   AGE   IP          NODE                                     NOMINATED NODE   READINESS GATES
kube-system   coredns-6d8c4cb4d-2clkj                                          0/1     Pending   0          86s   <none>      <none>                                   <none>           <none>
kube-system   coredns-6d8c4cb4d-8mznz                                          0/1     Pending   0          86s   <none>      <none>                                   <none>           <none>
kube-system   etcd-tiny-flannel-master-8-1.k8s.tcinternal                      1/1     Running   0          91s   10.31.8.1   tiny-flannel-master-8-1.k8s.tcinternal   <none>           <none>
kube-system   kube-apiserver-tiny-flannel-master-8-1.k8s.tcinternal            1/1     Running   0          92s   10.31.8.1   tiny-flannel-master-8-1.k8s.tcinternal   <none>           <none>
kube-system   kube-controller-manager-tiny-flannel-master-8-1.k8s.tcinternal   1/1     Running   0          90s   10.31.8.1   tiny-flannel-master-8-1.k8s.tcinternal   <none>           <none>
kube-system   kube-proxy-dkvrn                                                 1/1     Running   0          86s   10.31.8.1   tiny-flannel-master-8-1.k8s.tcinternal   <none>           <none>
kube-system   kube-scheduler-tiny-flannel-master-8-1.k8s.tcinternal            1/1     Running   0          92s   10.31.8.1   tiny-flannel-master-8-1.k8s.tcinternal   <none>           <none>

4.4 添加worker節點

這時候我們還需要繼續添加剩下的兩個節點作為worker節點運行負載,直接在剩下的節點上面運行集群初始化成功時輸出的命令就可以成功加入集群:

$ kubeadm join 10.31.8.1:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:d7160866920c0331731ad3c1c31a6e5b6c788b5682f86971cacaa940211db9ab
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

如果不小心沒保存初始化成功的輸出信息也沒有關系,我們可以使用kubectl工具查看或者生成token

# 查看現有的token列表
$ kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
abcdef.0123456789abcdef   23h         2022-05-08T06:27:34Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token

# 如果token已經失效,那就再創建一個新的token
$ kubeadm token create
pyab3u.j1a9ld7vk03znbk8
$ kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
abcdef.0123456789abcdef   23h         2022-05-08T06:27:34Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token
pyab3u.j1a9ld7vk03znbk8   23h         2022-05-08T06:34:28Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token

# 如果找不到--discovery-token-ca-cert-hash參數,則可以在master節點上使用openssl工具來獲取
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
d6cdc5a3bc40cbb0ae85776eb4fcdc1854942e2dd394470ae0f2f97714dd9fb9

添加完成之后我們再查看集群的節點可以發現這時候已經多了兩個node,但是此時節點的狀態還是NotReady,接下來就需要部署CNI了。

$ kubectl get nodes
NAME                                      STATUS     ROLES                  AGE     VERSION
tiny-flannel-master-8-1.k8s.tcinternal    NotReady   control-plane,master   7m49s   v1.23.6
tiny-flannel-worker-8-11.k8s.tcinternal   NotReady   <none>                 2m58s   v1.23.6
tiny-flannel-worker-8-12.k8s.tcinternal   NotReady   <none>                 102s    v1.23.6

5、安裝CNI

5.1 編寫manifest文件

flannel應該是眾多開源的CNI插件中入門門檻最低的CNI之一了,部署簡單,原理易懂,且相關的文檔在網絡上也非常豐富。

# 我們先把官方的yaml模板下載下來,然后對關鍵字段逐個修改
$ wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

針對kube-flannel.yml文件,我們需要修改一些參數以適配我們的集群:

  • net-conf.json參數,配置的是pod的網段,這里我們使用此前計劃好的10.8.64.0/18

      net-conf.json: |
        {
          "Network": "10.8.64.0/18",
          "Backend": {
            "Type": "vxlan"
          }
        }
    

5.2 部署flannel

修改完成之后我們直接部署即可

$ kubectl apply -f kube-flannel.yml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

# 查看pod是否正常運行
$ kubectl get pods -A
NAMESPACE     NAME                                                             READY   STATUS    RESTARTS   AGE
kube-system   coredns-6d8c4cb4d-np7q2                                          1/1     Running   0          14m
kube-system   coredns-6d8c4cb4d-z8f5b                                          1/1     Running   0          14m
kube-system   etcd-tiny-flannel-master-8-1.k8s.tcinternal                      1/1     Running   0          14m
kube-system   kube-apiserver-tiny-flannel-master-8-1.k8s.tcinternal            1/1     Running   0          14m
kube-system   kube-controller-manager-tiny-flannel-master-8-1.k8s.tcinternal   1/1     Running   0          14m
kube-system   kube-flannel-ds-9fq4z                                            1/1     Running   0          12m
kube-system   kube-flannel-ds-ckstx                                            1/1     Running   0          7m18s
kube-system   kube-flannel-ds-qj55x                                            1/1     Running   0          8m25s
kube-system   kube-proxy-bncfl                                                 1/1     Running   0          14m
kube-system   kube-proxy-lslcm                                                 1/1     Running   0          7m18s
kube-system   kube-proxy-pmwhf                                                 1/1     Running   0          8m25s
kube-system   kube-scheduler-tiny-flannel-master-8-1.k8s.tcinternal            1/1     Running   0          14m

# 查看flannel的pod日志是否有報錯
$ kubectl logs -f -l app=flannel -n kube-system

6、部署測試用例

集群部署完成之后我們在k8s集群中部署一個nginx測試一下是否能夠正常工作。首先我們創建一個名為nginx-quic的命名空間(namespace),然后在這個命名空間內創建一個名為nginx-quic-deploymentdeployment用來部署pod,最后再創建一個service用來暴露服務,這里我們先使用nodeport的方式暴露端口方便測試。

$ cat nginx-quic.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-quic

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-quic-deployment
  namespace: nginx-quic
spec:
  selector:
    matchLabels:
      app: nginx-quic
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-quic
    spec:
      containers:
      - name: nginx-quic
        image: tinychen777/nginx-quic:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-quic-service
  namespace: nginx-quic
spec:
  selector:
    app: nginx-quic
  ports:
  - protocol: TCP
    port: 8080 # match for service access port
    targetPort: 80 # match for pod access port
    nodePort: 30088 # match for external access port
  type: NodePort

部署完成后我們直接查看狀態

# 直接部署
$ kubectl apply -f nginx-quic.yaml
namespace/nginx-quic created
deployment.apps/nginx-quic-deployment created
service/nginx-quic-service created

# 查看deployment的運行狀態
$ kubectl get deployment -o wide -n nginx-quic
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                          SELECTOR
nginx-quic-deployment   2/2     2            2           48s   nginx-quic   tinychen777/nginx-quic:latest   app=nginx-quic

# 查看service的運行狀態
$ kubectl get service -o wide -n nginx-quic
NAME                 TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE   SELECTOR
nginx-quic-service   NodePort   10.8.4.218   <none>        8080:30088/TCP   62s   app=nginx-quic

# 查看pod的運行狀態
$ kubectl get pods -o wide -n nginx-quic
NAME                                     READY   STATUS    RESTARTS   AGE   IP          NODE                                      NOMINATED NODE   READINESS GATES
nginx-quic-deployment-696d959797-jm8w5   1/1     Running   0          73s   10.8.66.2   tiny-flannel-worker-8-12.k8s.tcinternal   <none>           <none>
nginx-quic-deployment-696d959797-lwcqz   1/1     Running   0          73s   10.8.65.2   tiny-flannel-worker-8-11.k8s.tcinternal   <none>           <none>

# 查看IPVS規則
$ ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30088 rr
  -> 10.8.65.2:80                 Masq    1      0          0
  -> 10.8.66.2:80                 Masq    1      0          0
TCP  10.8.4.218:8080 rr
  -> 10.8.65.2:80                 Masq    1      0          0
  -> 10.8.66.2:80                 Masq    1      0          0
TCP  10.8.64.0:30088 rr
  -> 10.8.65.2:80                 Masq    1      0          0
  -> 10.8.66.2:80                 Masq    1      0          0
TCP  10.8.64.1:30088 rr
  -> 10.8.65.2:80                 Masq    1      0          0
  -> 10.8.66.2:80                 Masq    1      0          0
TCP  10.31.8.1:30088 rr
  -> 10.8.65.2:80                 Masq    1      0          0
  -> 10.8.66.2:80                 Masq    1      0          0

最后我們進行測試,這個nginx-quic的鏡像默認情況下會返回在nginx容器中獲得的用戶請求的IP和端口

# 首先我們在集群內進行測試
# 直接訪問pod,這時候顯示的IP是master節點上面的flannel.1網卡的IP
$ curl 10.8.66.2:80
10.8.64.0:38958
$ curl 10.8.65.2:80
10.8.64.0:46484
# 直接訪問service的ClusterIP,這時請求會被轉發到pod中
$ curl 10.8.4.218:8080
10.8.64.0:26305
# 直接訪問nodeport,這時請求會被轉發到pod中,不會經過ClusterIP
$ curl 10.31.8.1:30088
10.8.64.0:6519

# 接著我們在集群外進行測試
# 直接訪問三個節點的nodeport,這時請求會被轉發到pod中,不會經過ClusterIP
# 由于externalTrafficPolicy默認為Cluster,nginx拿到的IP就是我們訪問的節點的flannel.1網卡的IP
$ curl 10.31.8.1:30088
10.8.64.0:50688
$ curl 10.31.8.11:30088
10.8.65.1:41032
$ curl 10.31.8.12:30088
10.8.66.0:11422
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容