暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

国内区域阿里云ECS使用kubeadm安装kubernetes cluster成功实践

零壹陋室 2021-09-18
1213

本文严重参考知呼上 爱做梦的锤子(以下简称“锤子同学”)文章,在其原文的指导下实践并完善修改而来。

操作系统:CentOS-7.8

kubernets版本:1.20.4

docker版本:20.10.8

本篇是一个K8S cluster安装教程,包含了docker安装,kubernetes安装以及kube-flannel网络插件的安装,整个安装过程使用的为国内网络环境,使用阿里云的镜像服务仓库完成大部分的镜像安装,少量部分image阿里云的镜像服务仓库也没有,仍然需要借助代理下载后load到服务器上,安装过程大致如下:


  1. 准备服务器,配置好主机名和IP,关闭防火墙,禁用SeLinux,关闭swap,配置k8s.conf,若服务器之前安装过docker可以将之前的docker卸载,避免安装过程中发生未知的问题

  2. 在服务器上配置docker和kubernetes的yum源,并安装docker和kubeadm、kubectl、kubectl

  3. 在master节点上进行kubeadm init初始化集群

  4. 在master节点上安装flannel网络插件

  5. 在worker节点上执行kubeadm join将其加入集群


这个环境建议作为学习环境,而不建议作为生产环境,原因例如flannel的槽糕性能——可以扩展学习一下MegeEase的K8S网络模型技术分享视频


准备4台虚拟机,其信息如下

#OSpublic ipprivate iprole
k8s01CentOS 7.88.130.*.*172.22.139.245

master

APISERVER

k8s02CentOS 7.88.130.*.*172.22.139.243worker
k8s03CentOS 7.88.130.*.*172.22.139.242worker
k8s04CentOS 7.88.130.*.*172.22.139.244worker

1、准备工作

1.1 服务器

服务准备工作包括以下几项:

  • 修改hosts文件

  • 关闭防火墙

  • 禁用SeLinux

  • 关闭Swap

  • 修改k8s.conf


修改4台服务器的 hosts文件 vim etc/hosts 加入以下内容

    172.22.139.245   k8s01    k8s01
    172.22.139.243 k8s02 k8s02
    172.22.139.242 k8s03 k8s03
    172.22.139.244 k8s04 k8s04
    复制


    针对上述四项操作,锤子同学准备了以下的小脚本,可以帮助你快速配置,当然你也可以一项一项的去操作,只要可以达到最终目的即可( 注意:4台服务器均需执行这些操作 )。

    操作脚本如下:

      #!/bin/bash


      #关闭防火墙,禁用防火墙开机自启动
      systemctl stop firewalld
      systemctl disable firewalld




      # 临时禁用SeLinux,重启失效
      setenforce 0
      # 修改SeLinux配置,永久禁用
      sed -i 's/^SELINUX=.*/SELINUX=disabled/' etc/selinux/config




      # 临时关闭Swap
      swapoff -a
      # 修改 etc/fstab 删除或者注释掉swap的挂载,可永久关闭swap
      sed -i '/swap/s/^/#/' etc/fstab




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


      2.1 卸载docker(可选)

      若你使用的服务器之前有安装过docker的,建议卸载原有docker后重新安装以避免遇到不确定的错误。当然如果你确定之前安装的docker是正常的服务,也可以忽略此步骤。

      若你需要卸载docker,则你需要卸载的服务包括:docker、docker-common、docker-selinux、docker-engine。卸载命令:

      yum remove docker docker-common docker-selinux docker-engine -y

      2 安装服务(docker,kubeadm,kubectl,kubelet)

      2.1 yum源准备

      安装kubernetes相关服务需要连接谷歌的相关服务下载软件已经镜像包,由于本次教程使用的国内网络,所以我们选用的阿里云的yum源以及镜像服务,我们需要添加 docker-ce 和 kubernetes 两个yum源,添加操作如下,同样本人也将其写成脚本的形式,便于使用。

        #!/bin/bash




        # 安装部分依赖
        yum install -y yum-utils device-mapper-persistent-data lvm2
        # 添加docker yum源
        sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
        # 添加kubernetes yum源
        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
        # 对新添加的源的软件包信息cache一下
        yum makecache -y
        复制


        2.2 安装docker与kubernetes相关服务

        由于我们上一步已经添加了yum源,所以安装这些服务,我们只需要使用yum命令即可安装,安装操作如下:

          #!/bin/bash


          #安装docker
          yum install -y docker-ce-*
          #启动docker并设置开机自启动
          systemctl enable docker
          systemctl start docker




          #安装kubernetes相关服务
          yum install -y kubelet kubeadm kubectl
          # 设置kuberlet为开机自启动
          systemctl enable kubelet
          systemctl start kubelet




          #输出docker和kubernetes的信息
          docker version
          kubectl version
          复制


          需要注意的一点是在我们安装完以上服务后,docker是会启动的,但是kubelet服务是还不具备启动的条件。master节点的kubelet服务在kubeadm init 成功后才会启动,worker节点的kubelet是在将节点加入集群后才会正常启动,所以在你组装好集群前,不要担心kubelet没有启动的问题。

          提示:如果kubelet启动失败,可以通过如下命令检查日志

            journalctl -eu kubelet | less
            复制


            2.3 修改docker配置阿里云镜像仓库,下载镜像

            修改/etc/docker/daemon.json文件,参考阿里云官方文档,这样就解决了原镜像仓库k8s.gcr.io无法访问的问题,大部分的镜像都可以从阿里云镜像仓库下载,少部分下不了的依靠代理解决,办法如下:

             coredns1.8.4在阿里云仓库上没有,如不提前pull否则init时报如下错误

              [root@k8s01 ~]# kubeadm init --apiserver-advertise-address=172.22.139.239 \
              > --image-repository registry.aliyuncs.com/google_containers \
              > --pod-network-cidr=10.244.0.0/16
              [init] Using Kubernetes version: v1.22.1
              [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'
              error execution phase preflight: [preflight] Some fatal errors occurred:
              [ERROR ImagePull]: failed to pull image registry.aliyuncs.com/google_containers/coredns:v1.8.4: output: Error response from daemon: manifest for registry.aliyuncs.com/google_containers/coredns:v1.8.4 not found: manifest unknown: manifest unknown
              , error: exit status 1
              [preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
              To see the stack trace of this error execute with --v=5 or higher
              复制


              查询原因应该是阿里云仓库没有coredns v1.8.4,手动pull镜像。先利用笔记本电脑的代理能力,从corends官方网站下载对应的tgz文件,然后传到服务器上,load进去,再tag改名。

              笔记本电脑上要安装docker,当然可以使用docker desktop ,然后配置好网络代理,注意配置时要带上协议(http),我发现这个docker desktop特别简陋,代理的语法写错了也不会报错,也不知道docker pull有没有走代理,结果我试了大半天,最后才按照别人的配置写法搞定,所以留个截图,务必按我图中的写法。

              在笔记本电脑上执行:

              docker save coredns/coredns:1.8.4 -o D:\Download\coredns1.8.4.tar

              这里特别注意不要使用docker save [image] > file.tar & docker load < file.tar 这种写法,因为大部分人的笔记本都是windows,而服务器是Linux,这种写法会导致因两者环境不一致,导致最后上传到服务器的文件不能正常被load

              在服务器上执行:

                [root@k8s01 ~]# docker load -i coredns1.8.4.tar
                225df95e717c: Loading layer 336.4kB/336.4kB
                f72781b18181: Loading layer 47.34MB/47.34MB
                Loaded image: coredns/coredns:1.8.4
                [root@k8s01 ~]# docker tag coredns/coredns:1.8.4 registry.aliyuncs.com/google_containers/coredns:v1.8.4
                [root@k8s01 ~]#
                [root@k8s01 ~]# docker images
                REPOSITORY TAG IMAGE ID CREATED SIZE
                coredns/coredns 1.8.4 9a4aa3cc30a7 2 minutes ago 47.3MB
                coredns/coredns latest 8d147537fb7d 3 months ago 47.6MB
                复制


                以上只是上传了一台服务器,不要忘记在所有master和worker节点服务器上都要load这些image!

                3、服务启动与集群创建(master和worker)

                3.1 修改cgroup

                可能是1.22.1版本的K8S的bug,cgroup与20.10.8版本的docker不同,如果不做修改,则init时报如下错误。

                注意master和worker节点上都要修改!

                  Aug  6 21:14:41 localhost kubelet: E0806 21:14:41.164994   72318 server.go:294] "Failed to run kubelet" err="failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"systemd\" is different from docker cgroup driver: \"cgroupfs\""
                  Aug 6 21:14:41 localhost systemd: kubelet.service: main process exited, code=exited, status=1/FAILURE
                  Aug 6 21:14:41 localhost systemd: Unit kubelet.service entered failed state.
                  Aug 6 21:14:41 localhost systemd: kubelet.service failed.
                  Aug 6 21:14:41 localhost systemd: Stopped kubelet: The Kubernetes Node Agent.
                  复制

                  原因:docker和k8s使用的cgroup不一致导致

                  说明:可以只修改docker,docker不再设置native.cgroupdriver=systemd,或将systemd改成cgroupfs,改成和k8s一样(k8s默认是cgroupfs,但是他竟然推荐用systemd,上文报错中可看出)。

                  修复方法如下:


                  1)重置,可将原配置文件删除

                    echo y | kubeadm reset
                    [reset] Reading configuration from the cluster...
                    [reset] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
                    W0909 08:13:46.818026 18291 reset.go:101] [reset] Unable to fetch the kubeadm-config ConfigMap from cluster: failed to get config map: Get "https://172.22.139.239:6443/api/v1/namespaces/kube-system/configmaps/kubeadm-config?timeout=10s": dial tcp 172.22.139.239:6443: connect: connection refused
                    [reset] WARNING: Changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
                    [reset] Are you sure you want to proceed? [y/N]: [preflight] Running pre-flight checks
                    W0909 08:13:46.818165 18291 removeetcdmember.go:80] [reset] No kubeadm config, using etcd pod spec to get data directory
                    [reset] Stopping the kubelet service
                    [reset] Unmounting mounted directories in "/var/lib/kubelet"
                    [reset] Deleting contents of config directories: [/etc/kubernetes/manifests etc/kubernetes/pki]
                    [reset] Deleting files: [/etc/kubernetes/admin.conf etc/kubernetes/kubelet.conf etc/kubernetes/bootstrap-kubelet.conf etc/kubernetes/controller-manager.conf etc/kubernetes/scheduler.conf]
                    [reset] Deleting contents of stateful directories: [/var/lib/etcd var/lib/kubelet var/lib/dockershim var/run/kubernetes var/lib/cni]


                    The reset process does not clean CNI configuration. To do so, you must remove etc/cni/net.d


                    The reset process does not reset or clean up iptables rules or IPVS tables.
                    If you wish to reset iptables, you must do so manually by using the "iptables" command.




                    If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
                    to reset your system's IPVS tables.




                    The reset process does not clean your kubeconfig files and you must remove them manually.
                    Please, check the contents of the $HOME/.kube/config file.
                    复制

                    2)更改docker cgroupdirver为systemd


                      [root@k8s01 ~]# cat etc/docker/daemon.json
                      {
                      "registry-mirrors": ["https://w446wc4o.mirror.aliyuncs.com"],
                      "exec-opts": ["native.cgroupdriver=systemd"]
                      }
                      复制


                      3)更改kubelet croupdriver为systemd


                        mkdir /var/lib/kubelet/
                        touch /var/lib/kubelet/config.yaml
                        cat > var/lib/kubelet/config.yaml <<EOF
                        apiVersion: kubelet.config.k8s.io/v1beta1
                        kind: KubeletConfiguration
                        cgroupDriver: systemd
                        EOF
                        复制

                        4)重启服务


                          systemctl daemon-reload
                          systemctl restart docker
                          复制

                          提示:如果中途修改错误,需要重新初始化master节点上的配置文件(删除配置文件),例如 kubeadm init 若多次执行,可以使用如下命令重置配置

                            echo y | kubeadm reset
                            复制


                            3.2 初始化master并启动集群

                            以上准备工作做完以后,可以在master节点上执行初始化命令,注意下面的ip是apiserver所在的服务器的云内私有地址(一般是master节点)

                              kubeadm init --apiserver-advertise-address=172.22.139.245 \
                              --image-repository registry.aliyuncs.com/google_containers \
                              --pod-network-cidr=10.244.0.0/16
                              复制


                              上述命令成功执行后后,后面会有一段输出内容如下所示,为了后续kubeadm join的动作,提示要记录下来

                                To start using your cluster, you need to run the following as a regular user:
                                #这三条命令在master节点依次执行
                                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
                                # 这个地方是说我们需要安装一个网络插件,我们接下来就会安装flannel网络
                                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:
                                #这个地方是其他worker节点加入该集群所要执行的命令,可以复制出来暂存一下,切记你要复制你自己主机上生成的
                                kubeadm join 192.168.56.111:6443 --token eud4cb.i6vf9rutybo9ve0u \
                                --discovery-token-ca-cert-hash sha256:dc89e4bf471b552e19b0c553910285014d93752398bbac7b6de23e455204c4aa
                                复制


                                3.3 配置KUBECONFIG环境变量

                                KUBECONFIG环境变量用于配置kubectl,配置完成后我们就可以使用kubectl进行集群管理了,如果不在环境变量中配置如下内容,则执行kubectl报错

                                  Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
                                  复制

                                  所以执行如下操作

                                    export KUBECONFIG=/etc/kubernetes/admin.conf




                                    vi ~/.bash_profile
                                    #add to env
                                    export KUBECONFIG=/etc/kubernetes/admin.conf
                                    复制


                                    3.4 安装flannel网络插件

                                    下载kube-flannel.yml,flannel网络的官方github地址 ,首先下载 kube-flannel.yml文件到本地,查看镜像名称image

                                    拉取flannel镜像到本地

                                      [root@k8s01 ~]# docker pull registry.cn-hangzhou.aliyuncs.com/k8sos/flannel:v0.14.0
                                      v0.14.0: Pulling from k8sos/flannel
                                      801bfaa63ef2: Pull complete
                                      e4264a7179f6: Pull complete
                                      bc75ea45ad2e: Pull complete
                                      78648579d12a: Pull complete
                                      3393447261e4: Pull complete
                                      071b96dd834b: Pull complete
                                      4de2f0468a91: Pull complete
                                      Digest: sha256:e383a3714fb4f3d9b4c8ca84196745b887b59633f0577c105364a3b3f5e061b0
                                      Status: Downloaded newer image for registry.cn-hangzhou.aliyuncs.com/k8sos/flannel:v0.14.0
                                      registry.cn-hangzhou.aliyuncs.com/k8sos/flannel:v0.14.0
                                      然后tag镜像名称,与kube-flannel.yml文件里相同
                                      [root@k8s01 ~]# docker tag registry.cn-hangzhou.aliyuncs.com/k8sos/flannel:v0.14.0 quay.io/coreos/flannel:v0.14.0
                                      复制

                                      应用flannel网络

                                        kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
                                        复制

                                        3.5 添加worker节点到集群

                                        直接在worker节点上执行我们在 kubeadm init 最后得到的那一段命令,格式如下:


                                          [root@k8s02 ~]# kubeadm join 172.22.139.239:6443 --token gcdxaj.3fc4i2dl2taihxxo         --discovery-token-ca-cert-hash sha256:16642fe5b55334bb760ea019d6d713b69ca34788cda6ea5e5958d3280702c49a
                                          [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.
                                          复制

                                          如果遇到启动失败的错误,很大的可能还是docker和k8s使用的cgroup不一致导致,所以还是采用上面的错误2的解决方案,但是最后一步不是执行kubeadm  init命令,而是执行kubeadm join命令。

                                          将worker节点添加到集群成功后,我们就可以使用 kubectl 来查看节点了

                                            # 查看所有节点
                                            kubectl get nodes
                                            # 得到如下效果,三个节点均运行成功
                                            # NAME STATUS ROLES AGE VERSION
                                            # k8s111 Ready control-plane,master 14m v1.20.4
                                            # k8s112 Ready <none> 24s v1.20.4
                                            # k8s113 Ready <none> 14s v1.20.4
                                            # 查看pods 集群搭建好,默认有一个kube-system命名空间,kubernetes自己的服务都部署在这个命名空间下
                                            kubectl get pod -n kube-system
                                            复制


                                            至此在国内网络环境下的一个kubernetes集群就搭建完成。

                                            提示:整个过程所需要使用的所有镜像,可以在操作前先拉取下来,加快效率,示例如下,注意版本可能不一致。

                                              docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.4
                                              docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.20.4
                                              docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.4
                                              docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.4
                                              docker pull registry.cn-hangzhou.aliyuncs.com/k8sos/flannel:v0.13.1-rc2
                                              docker pull registry.aliyuncs.com/google_containers/etcd:3.4.13-0
                                              docker pull registry.aliyuncs.com/google_containers/etcd:3.4.13-0
                                              docker pull registry.aliyuncs.com/google_containers/coredns:1.7.0
                                              docker pull registry.aliyuncs.com/google_containers/pause:3.2
                                              复制


                                              FQA:


                                              (1) 服务器因为访问不了外网,所以一些image只能通过笔记本电脑的代理pull以后,在笔记本上执行docker save打一个tar文件,传到服务器上再docker load,但是报如下错误:


                                              [root@k8s01 ~]# docker load < coredns1.8.4.tgz

                                              Error processing tar file(exit status 1): archive/tar: invalid tar header


                                              查询原因后,stackoverflow上有解释,原因在于windows与linux的字符差异,所以


                                              不要使用


                                              docker save [image] > file.tar followed by docker load < file.tar


                                              而要使用


                                              docker save [image] -o file.tar followed by docker load -i file.tar


                                              文章转载自零壹陋室,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                              评论