Skip to content

kubeadm搭建k8s踩坑指南

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。

官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/

这个工具能通过两条指令完成一个kubernetes集群的部署:

shell
# 创建一个 Master 节点
$ kubeadm init

# 将一个 Node 节点加入到当前集群中
$ kubeadm join <Master节点的IP和端口 >

1. 安装要求

部署Kubernetes 1.8.0 集群机器需要满足以下几个条件:

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
    • 这里采用 3 台机器(1-master 2/3-node)
  • 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
  • 集群中所有机器之间网络互通
  • 可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点
  • 禁止swap分区

(1) 在所有节点上安装 Docker 和 kubeadm

(2)部署 Kubernetes Master

(3)部署容器网络插件 CNI

(4)部署 Kubernetes Node,将节点加入 Kubernetes 集群中

(5)部署 kuboard 页面,可视化查看 Kubernetes 资源

2、准备环境

角色配置IP
master4核 8G 40G192.168.10.113
node14核 8G 40G192.168.10.114
node24核 8G 40G192.168.10.115

搭建完虚拟机后,由于 CentOS7.9 镜像问题,需要进行初始化

下面以 master 为例:

yum仓库源改为阿里云

shell
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bk
vi /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

[updates]
name=CentOS-$releasever - Updates - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

[centosplus]
name=CentOS-$releasever - Plus - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
shell
sudo yum clean all
sudo yum makecache
sudo yum update

静态IP|hostname配置

shell
vi /etc/sysconfig/network-scripts/ifcfg-ens33
DEVICE=ens33
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
NAME="ens33"
IPADDR=192.168.10.113
GATEWAY=192.168.10.2
DNS1=8.8.8.8

修改主机名称

shell
vi /etc/hostname
master

重启网络服务

systemctl restart network

安装基础工具

shell
yum install -y vim net-tools

关闭防火墙

shell
systemctl stop firewalld
systemctl disable firewalld

关闭 selinux

shell
# 永久操作
sed -i 's/enforcing/disabled/' /etc/selinux/config
shell
# 临时操作
setenforce 0

关闭 swap分区

shell
# 永久操作
vim /etc/fstab
# 注释掉或删除掉swap配置这一行
# /dev/mapper/centos-swap swap      swap    defaults        0 0
shell
# 临时操作
swapoff -a

添加主机名|IP对应关系

shell
vim /etc/hosts
192.168.10.113 master
192.168.10.114 node1
192.168.10.115 node2

将桥接的IPv4流量传递到iptables的链

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

刷新系统配置

shell
sysctl --system

时间同步

shell
yum install ntpdate -y
ntpdate time.windows.com

重启 master ,克隆 node1,node2 (修改 node1、node2 的 hostname 静态ip)。

3、部署

Kubernetes 1.8.0

image-20240521213714708

Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。

安装Docker

shell
yum install -y wget

wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

yum -y install docker-ce-18.06.1.ce-3.el7

systemctl enable docker && systemctl start docker
cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
$ docker --version
Docker version 18.06.1-ce, build e68fc7a

添加阿里云YUM软件源

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

安装kubeadm,kubelet和kubectl

由于版本更新频繁,这里指定版本号部署:

shell
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
shell
systemctl enable kubelet

部署Kubernetes Master

在192.168.10.113(Master节点)执行。

$ kubeadm init \
  --apiserver-advertise-address=192.168.10.113 \
  --image-repository registry.aliyuncs.com/google_containers \
  --kubernetes-version v1.18.0 \
  --service-cidr=10.96.0.0/12 \
  --pod-network-cidr=10.244.0.0/16
  • --apiserver-advertise-address 集群通告地址
  • --image-repository 由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址
  • --kubernetes-version K8s版本,与上面安装的一致
  • --service-cidr 集群内部虚拟网络,Pod统一访问入口
  • --pod-network-cidr Pod网络,与下面部署的CNI网络组件yaml中保持一致

这里如果是 v1.20.9版本 版本

所有机器添加master域名映射master节点(每个节点都需要执行,让每个节点知道master节点)

shell
echo "192.168.10.113  cluster-endpoint" >> /etc/hosts
shell
# v1.20.9版本
kubeadm init \
--apiserver-advertise-address=192.168.10.113 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16

拷贝kubectl使用的连接k8s认证文件到默认路径:

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

加入Kubernetes Node

在192.168.10.114/115(Node节点)执行。

向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:

$ kubeadm join 192.168.10.113:6443 --token esce21.q6hetwm8si29qxwn \
    --discovery-token-ca-cert-hash sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5

默认token有效期为24小时,当过期之后,该token就不可用了。这时就需要重新创建token,操作如下:

kubeadm token create --print-join-command

部署CNI网络插件

Flannel

Flannel是CoreOS维护的一个网络组件,Flannel为每个Pod提供全局唯一的IP,Flannel使用ETCD来存储Pod子网与Node IP之间的关系。flanneld守护进程在每台主机上运行,并负责维护ETCD信息和路由数据包。

shell
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

默认镜像地址无法访问,sed命令修改为docker hub镜像仓库。

shell
sed -i -r "s#quay.io/coreos/flannel:.*-amd64#lizhenliang/flannel:v0.11.0-amd64#g" kube-flannel.yml
shell
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-system
NAME                          READY   STATUS    RESTARTS   AGE
kube-flannel-ds-amd64-2pc95   1/1     Running   0          72s

calico(与上面二选一)

shell
curl https://docs.projectcalico.org/v3.21/manifests/calico.yaml -O
shell
kubectl apply -f calico.yaml
shell
#查看网络组件是否安装完成
kubectl get pods -n kube-system

查看pod|node状态

shell
kubectl get pod --all-namespaces
shell
kubectl get node

测试kubernetes集群

在Kubernetes集群中创建一个pod,验证是否正常运行: 访问地址:http://192.168.10.113:32614

shell
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pod,svc

部署dashboard

访问地址:https://192.168.10.113:30001

shell
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml

默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:

shell
vi recommended.yaml
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001
  type: NodePort
  selector:
    k8s-app: kubernetes-dashboard
shell
kubectl apply -f recommended.yaml
kubectl get pods -n kubernetes-dashboard
NAME                                         READY   STATUS    RESTARTS   AGE
dashboard-metrics-scraper-6b4884c9d5-gl8nr   1/1     Running   0          13m
kubernetes-dashboard-7f99b75bf4-89cds        1/1     Running   0          13m

创建service account并绑定默认cluster-admin管理员集群角色:

shell
# 创建用户
$ kubectl create serviceaccount dashboard-admin -n kube-system
# 用户授权
$ kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
# 获取用户Token
$ kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
eyJhbGciOiJSUzI1NiIsImtpZCI6InNpNlAxUzRSQUdRb1hvSnNuMmZEQVFvLUhOeTJHMXlLYW9nZmxjZ0syZkkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZ2p4d3QiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNjJjZWRjYWQtMzIzYS00NzAxLTkxYjEtY2IyNTJjZDFjODI2Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.NPNrfbpJpqrR8F-_CpO9Ym5r2mjatcAXEhAwa6W5jmBeq_vgHya8uLvgi6mUK2YfD62sUGE3ipHouOasafqXHsb3uM2bYYZ7TSr5iEA7k06iGEFYZyWtUz3j591VWYBCVM9EYkdhsHg6CeAdv2PZs0ZGkQMGDTtnO-vA8l-3d97ciKhxRJItIBpW-JNbG83uXMhdUgnioSec7XQINSMdqiIHN2mxbC9nuh8zPujIjnSoSR0qz669l3-81KyqB7CgiIEUjTcv4NIfGNMHfYvHcY8sLvOiHyoLOJQCW2t5cjVmQPphDUApoK_DKQLS-dj5pf38C_HgB9uJNPns8qfH9w

使用输出的token登录Dashboard。

问题与解决方案

Q:k8s 组件卸载

移除旧版本docker

shell
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

移除旧版本的k8s组件

shell
# 查看当前正在运行的K8S服务
sudo systemctl status kubelet
sudo systemctl status kube-proxy

# 停止正在运行的k8s服务
sudo systemctl stop kubelet
sudo systemctl stop kube-proxy

# 查询已安装的k8s包
yum list installed grep kube
# 移除k8s包
sudo yum remove kubelet kubeadm kubectl kubernetes
# 清除k8s的相关配置文件和数据
sudo rm-rf /etc/kubernetes
sudo rm-rf /var/lib/kubelet
sudo rm-rf /var/lib/etcd

Q:部署cni网络 raw.githubusercontent.com无法连接

解决方案:

shell
sudo vim /etc/hosts

添加以下内容

shell
# GitHub Start
52.74.223.119 github.com
192.30.253.119 gist.github.com
54.169.195.247 api.github.com
185.199.111.153 assets-cdn.github.com
151.101.76.133 raw.githubusercontent.com
151.101.108.133 user-images.githubusercontent.com
151.101.76.133 gist.githubusercontent.com
151.101.76.133 cloud.githubusercontent.com
151.101.76.133 camo.githubusercontent.com
151.101.76.133 avatars0.githubusercontent.com
151.101.76.133 avatars1.githubusercontent.com
151.101.76.133 avatars2.githubusercontent.com
151.101.76.133 avatars3.githubusercontent.com
151.101.76.133 avatars4.githubusercontent.com
151.101.76.133 avatars5.githubusercontent.com
151.101.76.133 avatars6.githubusercontent.com
151.101.76.133 avatars7.githubusercontent.com
151.101.76.133 avatars8.githubusercontent.com
# GitHub End

Q:no configuration has been provided, try setting KUBERNETES_MASTER environment variable

  1. 在k8s 的master节点可以看到 admin.conf
shell
$ pwd
/etc/kubernetes
$ ls
admin.conf  controller-manager.conf  kubelet.conf  manifests  pki  scheduler.conf
  1. 在主节点移动 admin.conf 到node
shell
scp admin.conf root@192.168.10.114:/etc/kubernetes
shell
scp admin.conf root@192.168.10.115:/etc/kubernetes
  1. 在node节点添加变量
shell
export KUBECONFIG=/etc/kubernetes/admin.conf
shell
source /etc/profile
  1. node节点可以看到了
shell
kubectl get node

Q:k8s镜像无法加载

  1. 通过 docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.8.0 拉取到本地 docker
  2. 修改 xxxxx.yaml 文件,检索 /image: ,将 地址 修改为 registry.aliyuncs.com/google_containers 或者 用自己的私有镜像库(这里我用 阿里云的 私有镜像库 进行 同步)

Q:k8s flannel 网络插件无法加载 导致集群无法启动

  1. 手动下载 flannel 组件 ,上传至 /opt/cni/bin
  2. 等待集群自动恢复

Q:一些简单的k8s命令

  1. 获取所有k8s pod/service/deployment
shell
kubectl get all
  1. 删除容器: 1.先删除deployment 2.再删除service
shell
kubectl delete deployment kubernetes-dashboard --namespace=kube-system
kubectl delete service kubernetes-dashboard --namespace=kube-system

附录

参考文档

集群部署笔记

kubectl 文档

kubectl 命令参考