Kubernetes集群搭建

先期工作

机器集群实现方案

手头并没有现成的机器群,但好在有一台还算高配的MacBook Pro,如此的话可以在其上借助于虚拟机构建出一个5台机器的集群,在此基础上来搭建Kubernetes集群:

1
2
3
4
MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
Processor: 2.5 GHz Dual-Core Intel Core i7
Memory: 16 GB 2133 MHz LPDDR3
Graphics: Intel Iris Plus Graphics 640 1536 MB
项目 选件 理由
虚拟机 VirtualBox 主要考虑Oracle Virtual Box和VMware Fusion,Vbox提供丰富
的命令工具来操作虚拟机,这使得我们能够方便地基于此来编写
一些控制脚本方便地控制集群机器,所以虚拟机选择VBox
操作系统 CentOS 7.9 主要考虑的是主流的RHEL、CentOS、Fedora、Ubuntu等等,
RHEL/CentOS/Fedora同出一脉,Fedora作为试验先行版自然是不考虑
了,CentOS比较主流,是首选,版本的话也是选择目前的主流版本7

Kubernetes集群设计

计划使用6台虚拟机来构建集群,集群机器的IP、Hostname等的设计如下:

Hostname IP Address 备注说明
worker-st.xcluster.io 192.168.99.100 不作为K8s集群的一部分,而是安装
jenkins/gitlab….等CICD Devops工具
worker-01.xcluster.io 192.168.99.101 作为K8s集群的master节点,负责管理其他节点
worker-02.xcluster.io 192.168.99.102 作为K8s集群的1号Node机器,负责跑Pods
worker-03.xcluster.io 192.168.99.103 作为K8s集群的2号Node机器,负责跑Pods
worker-04.xcluster.io 192.168.99.104 作为K8s集群的3号Node机器,负责跑Pods
worker-05.xcluster.io 192.168.99.105 作为K8s集群的4号Node机器,负责跑Pods

参考文档列表

创建服务器群

创建CentOS7样机

这一步的目的是创建出一台基础的CentOS7虚拟机并做好基础设置,然后基于该机器再克隆出其他机器,首先是创建第一台(worker-st.xcluster.io)并完成基本配置:

  • 下载安装VBox:https://www.virtualbox.org/wiki/Downloads

  • 下载CentOS7.9镜像:http://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/

  • 安装好VBox后创建一个虚拟机,配置如下:

    • 名称:Worker-st、类型:Linux、版本:Red Hat (64bit)

    • 内存:4096MB、CPU:双核、显存:64MB、显示器:2个、显示器显示比例:200%

    • 磁盘类型:Normal (VMDK)、磁盘容量:300.00 GB(单个文件、动态增长)

    • 网卡1:NAT、适配器类型:Paravirtualized Network (virtio-net) —— 用以跟MBP共享网络

    • 网卡2:Host-only Adapter — — 用以设置静态IP(192.168.99.XX)

      两张网卡的Promiscuous Mode均为默认值:Deny

在虚拟机磁盘中选择下载好的CentOS 7.9的ISO镜像,然后启动虚拟机进行系统安装,安装期间系统设置如下:

  • 语言:English (United States)、键盘:English (United States)
  • 磁盘分区:自动、Root密码:123456abc、创建管理账户:fury,密码为:123456abc

安装完成后以root登录,然后设置静态IP,这样可以直接从MBP的Terminal远程登录进机器,操作更方便一些(直接从虚拟机的黑框框登录的话,由于显示比例的问题,操作不是很方便):

  • 安装net-tools(包含ifconfig):$ sudo yum install net-tools

  • 启用SSH登录:添加MBP的公钥到~/.ssh/authorized_keys,重启SSHD,修改.ssh目录权限

    1
    2
    3
    $ sudo service sshd restart
    $ sudo chmod 700 ~/.ssh
    $ sudo chmod 600 ~/.ssh/authorized_keys
  • 设置静态IP

    • 设置DNS $ sudo vi /etc/resolv.conf,加入nameserver 114.114.114.114

    • 查看现有网卡:$ ifconfig -a

    • 配置两张网卡(路径/etc/sysconfig/network-scripts/):

      • 备份enp0s3配置文件,并拷贝为ifcfg-eth0,内部改name和device为eth0(如果文件内没有HWADDR字段则加上,值为虚拟机网卡设置那里看到的MAC地址HWADDR=00:0C:29:7C:00:34),修改ONBOOT=yes 以自启动网卡

      • 创建ifcfg-eth1文件,设置内容如下(配置第二张网卡为静态IP):

        1
        2
        3
        4
        5
        6
        7
        DEVICE=eth1
        HWADDR=00:0C:29:84:35:09
        ONBOOT=yes
        BOOTPROTO=static
        IPADDR=192.168.99.100
        NETMASK=255.255.255.0
        NAME=eth1

        HWADDR为虚拟机上第二张网卡的MAC地址

        然后重启:$ sudo service network restart,可能会发现提示错误

        查看$ sudo journalctl -xe或查看错误日志看看是哪个网卡没起来:$ cat /var/log/messages | grep network,发现说eth0没起来,它的UUID和eth1冲突了,把eth0的UUID删掉(确认HWADDR是第一张网卡的MAC地址),然后重启即可(UUID会自动加上)。

重启系统,这样以后就可以通过MBP的Terminal如下命令开启、登录、关闭虚拟机(XXX为虚拟机名称):

  1. 开启虚拟机:$ VBoxManage startvm XXX -type vrdp
  2. 登录虚拟机:$ ssh [email protected]
  3. 关闭虚拟机:$ VBoxManage controlvm XXX poweroff

其他的基础设置:

  • 安装wget下载工具:$ sudo yum install wget

  • 修改hostname:$ sudo vi /etc/hostname,设置为worker-st.xcluster.io

  • 修改shell显示名:$ sudo vi ~/.bashrc添加export PS1='[\[email protected] \W]\$ '

  • 使用阿里云的Repo(备份原/etc/yum.repos.d/下的repo文件然后清空该文件夹):

    1
    2
    3
    4
    5
    $ cd /etc/yum.repos.d/
    $ wget http://mirrors.aliyun.com/repo/Centos-7.repo
    $ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    $ wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
    $ yum clean all && yum makecache
  • 安装Vim8.x:

    • 安装所需的基础库:

      1
      $ yum install -y gcc gcc-c++ ruby ruby-devel lua lua-devel ctags git python python-devel tcl-devel ncurses-devel perl perl-devel perl-ExtUtils-ParseXS perl-ExtUtils-CBuilder perl-ExtUtils-Embed
    • 下载Vim-v8.1:

      1
      2
      3
      $ wget https://github.com/vim/vim/archive/v8.1.1312.tar.gz
      $ tar -zxvf v8.1.1312.tar.gz
      $ cd vim-8.1.1312
    • 开始安装:--with-python-config-dir这项要看自己的实际路径,是python-devel带的目录

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      $ ./configure --with-features=huge \
      --enable-multibyte \
      --enable-rubyinterp=yes \
      --enable-pythoninterp=yes \
      --with-python-config-dir=/usr/lib64/python2.7/config \
      --enable-perlinterp=yes \
      --enable-luainterp=yes \
      --enable-cscope \
      --prefix=/usr/local
      $ make -j4 VIMRUNTIMEDIR=/usr/local/share/vim/vim81 all
      $ sudo sudo make -j4 install
    • 更改系统默认编辑器并将vi指向vim

      1
      2
      3
      4
      $ sudo update-alternatives --install /usr/bin/editor editor /usr/local/bin/vim 1
      $ sudo update-alternatives --set editor /usr/local/bin/vim
      $ sudo update-alternatives --install /usr/bin/vi vi /usr/local/bin/vim 1
      $ sudo update-alternatives --set vi /usr/local/bin/vim
  • 安装其他基础软件:

    1
    2
    $ sudo yum install unzip zip
    $ sudo yum install gcc gcc-c++ glibc

至此,我们创建好了一台基础的CentOS7虚拟机,这台机器将作为集群设计里面的第一台worker-st.xcluster.io

创建Kubernetes样机

这一步在创建好的CentOS7虚拟机样机的基础上安装Kubernetes集群都需要安装的一些组件。从上一步创建好的虚拟机克隆出一台新的虚拟机,克隆时名称改为Worker-01并选择完全克隆方式。克隆完成后在虚拟机的网卡设置当中刷新两张网卡的MAC地址,然后启动虚拟机,进入虚拟机后做如下修改:

注意:后面基于这台机器克隆其他k8s集群机器时也要做如下这些方面对应的修改

  • 修改eth0和eth1的MAC地址和eth1的IP地址(路径/etc/sysconfig/network-scripts/
    • eth0和eth1的MAC地址(HWADDR)可以从虚拟网卡设置界面获得
    • IP地址按照一开始的设计,我们把IP改为192.168.99.101
  • 修改hostname为worker-01.xcluster.io
  • 修改shell显示名:$ vi ~/.bashrc添加export PS1='[\[email protected] \W]\$ '

其他为Kubernetes进行的配置:

  • 关闭防火墙:$ sudo systemctl stop firewalld && systemctl disable firewalld

  • 永久关闭selinux:$ sudo vim /etc/selinux/config修改:

    1
    2
    #SELINUX=enforcing
    SELINUX=disabled
  • 永久关闭swap:$ sudo vim /etc/fstab 注释最后一行(swap)

  • 配置yum源(自带的kubernetes版本可能比较低):安装方式(生产,kubeadmin)

    • $ cd /etc/yum.repos.d/

    • $ vim kubernetes.repo

      1
      2
      3
      4
      5
      6
      7
      [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
    • $ sudo yum clean all && yum makecache

  • 安装docker

    1
    2
    $ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    $ sudo yum -y install docker

    由于内核可能不支持 overlay2所以需要升级内核或者禁用overlay2(选择禁用,安装完docker可以启动docker测试下是否支持,启动docker不报错的可以忽略这一步):$ sudo vim /etc/sysconfig/docker修改--selinux-enabled=false

  • 自启动docker服务:$ sudo systemctl start docker && systemctl enable docker

  • 设置服务器时区:$ sudo timedatectl set-timezone Asia/Shanghai

  • 设置k8s相关参数:

    • $ sudo vim /etc/sysctl.d/k8s.conf

      1
      2
      net.bridge.bridge-nf-call-ip6tables = 1
      net.bridge.bridge-nf-call-iptables = 1
    • 让其生效

      1
      2
      $ sudo sysctl -p
      $ sudo echo "1" > /proc/sys/net/ipv4/ip_forward
  • 安装k8s相关安装包,使用 $ sudo yum list kube* 来查看当前yum源支持的最新版本(这里是1.20.1-0)

    1
    $ sudo yum -y install kubeadm-1.20.1-0 kubelet-1.20.1-0 kubectl-1.20.1-0
  • 自启动服务:$ sudo systemctl restart kubelet && systemctl enable kubelet

到这里完成了第二台样机设置,这台机器将作为k8s集群的master机器(worker-01.xcluster.io),其他机器将以这台为样本进行克隆配置。

克隆其他K8s集群机器

基于第二台样机(worker-01.xcluster.io),克隆出其他的4台机器,注意按上面的提示对应修改MAC地址、IP、hostname、shell显示名等相关信息:

Hostname IP Address 备注说明
worker-02.xcluster.io 192.168.99.102 集群1号Node机器
worker-03.xcluster.io 192.168.99.103 集群2号Node机器
worker-04.xcluster.io 192.168.99.104 集群3号Node机器
worker-05.xcluster.io 192.168.99.105 集群号Node机器

配置K8s集群

到这里,我们创建好了6台CentoOS服务器,第一台后面作为安装Jenkins/gitlab等工具的机器,不纳入k8s集群,后面5台都安装了k8s相关包和docker,这5台将作为我们的k8s集群机器,这些机器的配置目前是一样的,接下来对第一台机器(worker-01.xcluster.io)进行设置(初始化k8s集群让其成为master)。

初始化配置Master

在master机器上执行初始化操作,即worker-01.xcluster.io这台机;注意坑点:

  • 如果要用flannel:
  • 如果要用weave:
    • 安装前,使用kubeadm init的时候,参数里记得不要指定service-cidr参数,但要保留pod-network-cidr. 不然内置的DNS会出问题,这可能是系统的bug。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ sudo kubeadm init \
--apiserver-advertise-address=192.168.99.101 \ # 写masterIP地址即可
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.20.1 \ # 注意是v1.20.1而不是v1.20.1-0
--service-cidr=10.2.0.0/16 \
--pod-network-cidr=10.244.0.0/16

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 192.168.99.101:6443 --token 9k35nl.lyfuzdlxzqbwonsr \
--discovery-token-ca-cert-hash sha256:91f6bd754f302b858b02d02f16e164d72b39a9ebcba841931e1e80388fd91910

[[email protected] ~]$

可以看到初始化已经OK了,通过26行的代码可以在其他node上执行以让master发现(加入k8s集群)。

到这里master就初始化完毕了。

其他节点加入K8s集群

  • 将node节点加入到master集群中,在需要加入k8s集群的node节点上执行该命令(上面的输出)

    1
    2
    $ sudo kubeadm join 192.168.99.101:6443 --token 9k35nl.lyfuzdlxzqbwonsr \
    --discovery-token-ca-cert-hash sha256:91f6bd754f302b858b02d02f16e164d72b39a9ebcba841931e1e80388fd91910

    如果忘记kubeadm join后的参数,可用通过下面命令来获取新的:

    1
    $ sudo kubeadm token create --print-join-command

    在Worker-02上的操作结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [[email protected] ~]$ sudo kubeadm join 192.168.99.101:6443 --token 9k35nl.lyfuzdlxzqbwonsr     --discovery-token-ca-cert-hash sha256:91f6bd754f302b858b02d02f16e164d72b39a9ebcba841931e1e80388fd91910 
    [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.

    [[email protected] ~]$

在其他的Worker上执行相同操作来加入集群,正常的话在master上执行``即可看到其他node的状态:

1
2
3
4
5
6
7
8
[[email protected]rker-01 ~]$ sudo kubectl get nodes
NAME STATUS ROLES AGE VERSION
worker-01.xcluster.io Ready control-plane,master 2d22h v1.20.1
worker-02.xcluster.io Ready <none> 2d22h v1.20.1
worker-03.xcluster.io Ready <none> 2d17h v1.20.1
worker-04.xcluster.io Ready <none> 2d17h v1.20.1
worker-05.xcluster.io Ready <none> 2d17h v1.20.1
[[email protected] ~]$

常用的kubernetes命令

  • $ sudo systemctl start|restart|stop kubelet:开启、重启、停止kubelet
  • $ sudo systemctl status -l kubelet:查看集群启动状态
  • $ sudo jornalctl -f -u kubelet:查看集群日志
  • $ sudo kubectl get <node|nodes>:列出所有node(及其状态)
  • $ sudo kubectl delete node|nodes> <node name>:删除集群节点
  • $ sudo kubectl get <pod|pods> [-n <namespace>]:列出所有的pods
  • $ sudo kubectl get <svc|service|services> [-n <namespace>]:列出所有的服务
  • $ sudo kubectl apply -f <deployment.yml>:部署一个服务
  • $ sudo kubectl delete -f <deployment.yml>:移除一个服务
  • $ sudo kubectl logs -f <pod name> [-n <namespace>]:查看某个pod日志

安装配置过程中的问题

  • 在master上执行$ sudo kubectl get nodes报错:The connection to the server localhost:8080 was refused - did you specify the right host or port?

    解决:

    1
    2
    $ echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
    $ sudo source ~/.bash_profile
  • 执行完$ sudo kubeadm join后在master节点执行$ sudokubectl get nodes 发现Node节点状态为NotReady;

    在node节点查看日志$ sudo journalctl -f -u kubelet找到具体错误原因:

    summary_sys_containers.go:47] Failed to get system container stats for “/system.slice/kubelet.service”: failed to get cgroup stats for “/system.slice/kubelet.service”: failed to get container info for “/system.slice/kubelet.service”: unknown container “/system.slice/kubelet.service”

    解决:是kubernetes和docker版本兼容性问题,启动时添加参数:**–runtime-cgroups=/systemd/system.slice –kubelet-cgroups=/systemd/system.slice**即可:

    • 开机自启动的服务是通过$ sudo systemctl enable xxx来配置,该命令执行后会在/etc/systemd/system/multi-user.target.wants/目录下新建一个/usr/lib/systemd/system/xxx.service的文件并创建软连接到当前目录

    • /usr/lib/systemd/system/xxx.service同目录下找到kubelet.service.d文件夹,有个/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf文件,编辑,在KUBELET_CGROUP_ARGS属性添加:

      1
      --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice

      如果不存在”KUBELET_CGROUP_ARGS”属性则新增,同时在ExecStart=/usr/bin/kubelet ....后新增$KUBELET_CGROUP_ARGS

      10-kubeadm.conf的路径网上提到的多为:*/etc/systemd/system/kubelet.service.d/10-kubeadm.conf*,本人的机器路径为:/usr/lib/systemd/system/kubelet.service.d

      然后重启$ sudo systemctl daemon-reload && systemctl restart kubelet即可解决。

  • 执行$ sudo journalctl -f -u kubelet或者$ sudo systemctl status -l kubelet发现日志中存在错误或警告:

    • Unable to read config path “/etc/kubernetes/manifests”: path does not exist, ignoring

      解决:执行$ sudo mkdir -p /etc/kubernetes/manifests然后重启kubelet。

    • failed to sync configmap cache: timed out waiting for the condition

      解决:新增(编辑)/var/lib/kubelet/config.yaml添加

      1
      2
      featureGates:
      CSIMigration: false

      然后重启所有node。

    • failed to collect filesystem stats - rootDiskErr: could not stat

      解决:不支持overlay2导致的,编辑docker配置 $ sudo vim /etc/sysconfig/docker修改--selinux-enabled=false 然后重启docker$ sudo systemctl restart docker

    • MemoryAccounting not enabled for pid: 1215, CPUAccounting not enabled for pid: 1208

      查看这两个进程:$ sudo ps -a 1208# ps -a 1215

      1
      2
      3
      4
      5
      6
      7
      8
      [[email protected] ~]$ sudo ps -a 1208
      PID TTY STAT TIME COMMAND
      1208 ? Ssl 0:12 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=d
      8015 pts/0 R+ 0:00 ps -a 1208
      [[email protected] ~]$ sudo ps -a 1215
      PID TTY STAT TIME COMMAND
      1215 ? Ssl 0:32 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/ku
      8079 pts/0 R+ 0:00 ps -a 1215

      查看内存使用情况:$ free -h

      1
      2
      3
      4
      5
      [[email protected] ~]$ free -h
      total used free shared buff/cache available
      Mem: 3.7G 868M 2.0G 10M 840M 2.6G
      Swap: 0B 0B 0B
      [[email protected] ~]$

      并没有存在内存不够的情况。

      解决:明确指定DefaultCPUAccountingDefaultMemoryAccounting即可

      1
      2
      3
      4
      5
      6
      $ sudo mkdir -p /etc/systemd/system.conf.d
      $ sudo vim /etc/systemd/system.conf.d/kubernetes-accounting.conf
      [Manager]
      DefaultCPUAccounting=yes
      DefaultMemoryAccounting=yes
      $ sudo systemctl daemon-reload && systemctl restart kubelet
  • 执行$ sudo kubectl get pods: No resources found in default namespace

    解决:不指定命名空间时默认在default这个命名空间;通过**-n**参数指定,系统命名空间为kube-system

    1
    $ sudo kubectl get pods -n kube-system

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×