美文网首页
Kubernets集群部署(二进制包编译方式)

Kubernets集群部署(二进制包编译方式)

作者: 码农工号9527 | 来源:发表于2023-09-25 22:36 被阅读0次

    参考文章:https://www.cnblogs.com/chiangchou/p/k8s-1.html

    一、简介

    1、Kubernetes 是什么

    Kubernetes 是一个全新的基于容器技术的分布式架构解决方案,是 Google 开源的一个容器集群管理系统,Kubernetes 简称 K8S。

    Kubernetes 是一个一站式的完备的分布式系统开发和支撑平台,更是一个开放平台,对现有的编程语言、编程框架、中间件没有任何侵入性。

    Kubernetes 提供了完善的管理工具,这些工具涵盖了开发、部署测试、运维监控在内的各个环节。

    Kubernetes 具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制、多粒度的资源配额管理能力。

    Kubernetes 官方文档:https://kubernetes.io/zh/

    2、Kubernetes 特性

    ① 自我修复

    在节点故障时,重新启动失败的容器,替换和重新部署,保证预期的副本数量;杀死健康检查失败的容器,并且在未准备好之前不会处理用户的请求,确保线上服务不中断。

    ② 弹性伸缩

    使用命令、UI或者基于CPU使用情况自动快速扩容和缩容应用程序实例,保证应用业务高峰并发时的高可用性;业务低峰时回收资源,以最小成本运行服务。

    ③ 自动部署和回滚

    K8S采用滚动更新策略更新应用,一次更新一个Pod,而不是同时删除所有Pod,如果更新过程中出现问题,将回滚更改,确保升级不影响业务。

    ④ 服务发现和负载均衡

    K8S为多个容器提供一个统一访问入口(内部IP地址和一个DNS名称),并且负载均衡关联的所有容器,使得用户无需考虑容器IP问题。

    ⑤ 机密和配置管理

    管理机密数据和应用程序配置,而不需要把敏感数据暴露在镜像里,提高敏感数据安全性。并可以将一些常用的配置存储在K8S中,方便应用程序使用。

    ⑥ 存储编排

    挂载外部存储系统,无论是来自本地存储,公有云,还是网络存储,都作为集群资源的一部分使用,极大提高存储使用灵活性。

    ⑦ 批处理

    提供一次性任务,定时任务;满足批量数据处理和分析的场景。

    二、集群架构与组件

    Kubernetes 集群架构以及相关的核心组件如下图所示:一个 Kubernetes 集群一般包含一个 Master 节点和多个 Node 节点,一个节点可以看成是一台物理机或虚拟机。


    1、Master

    Master 是 K8S 的集群控制节点,每个 K8S 集群里需要有一个 Master 节点来负责整个集群的管理和控制,基本上 K8S 所有的控制命令都是发给它,它来负责具体的执行过程。Master 节点通常会占据一个独立的服务器,因为它太重要了,如果它不可用,那么所有的控制命令都将失效。

    Master 节点上运行着以下关键组件:

    kube-apiserver

    是集群的统一入口,各组件协调者,以 HTTP Rest 提供接口服务,所有对象资源的增、删、改、查和监听操作都交给 apiserver 处理后再提交给 Etcd 存储。

    kube-controller-manager

    是 K8S 里所有资源对象的自动化控制中心,处理集群中常规后台任务,一个资源对应一个控制器,而 controller-manager 就是负责管理这些控制器的。

    kube-scheduler

    根据调度算法为新创建的 Pod 选择一个 Node 节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上。

    etcd

    是一个分布式的,一致的 key-value 存储,主要用途是共享配置和服务发现,保存集群状态数据,比如 Pod、Service 等对象信息。

    2、Node

    除了 Master,K8S 集群中的其它机器被称为 Node 节点,Node 节点是 K8S 集群中的工作负载节点,每个 Node 都会被 Master 分配一些工作负载,当某个 Node 宕机时,其上的工作负载会被 Master 自动转移到其它节点上去。

    每个 Node 节点上都运行着以下关键组件:

    kubelet

    kubelet 是 Master 在 Node 节点上的 Agent(代理),与 Master 密切协作,管理本机运行容器的生命周期,负责 Pod 对应的容器的创建、启停等任务,实现集群管理的基本功能。

    kube-proxy

    在 Node 节点上实现 Pod 网络代理,实现 Kubernetes Service 的通信,维护网络规则和四层负载均衡工作。

    docker engine

    Docker 引擎,负责本机的容器创建和管理工作。

    Node 节点可以在运行期间动态增加到 K8S 集群中,前提是这个节点上已经正确安装、配置和启动了上述关键组件。在默认情况下 kubelet 会向 Master 注册自己,一旦 Node 被纳入集群管理范围,kubelet 就会定时向 Master 节点汇报自身的情况,例如操作系统、Docker 版本、机器的 CPU 和内存情况,以及之前有哪些 Pod 在运行等,这样 Master 可以获知每个 Node 的资源使用情况,并实现高效均衡的资源调度策略。而某个 Node 超过指定时间不上报信息时,会被 Master 判定为“失联”,Node 的状态被标记为不可用(Not Ready),随后 Master 会触发“工作负载大转移”的自动流程。

    三、核心概念

    1、Pod

    Pod 是 K8S 中最重要也是最基本的概念,Pod 是最小的部署单元,是一组容器的集合。每个 Pod 都由一个特殊的根容器 Pause 容器,以及一个或多个紧密相关的用户业务容器组成。

    Pause 容器作为 Pod 的根容器,以它的状态代表整个容器组的状态。K8S 为每个 Pod 都分配了唯一的 IP 地址,称之为 Pod IP。Pod 里的多个业务容器共享 Pause 容器的IP,共享 Pause 容器挂载的 Volume。

    2、Label

    标签,附加到某个资源上,用于关联对象、查询和筛选。一个 Label 是一个 key=value 的键值对,key 与 value 由用户自己指定。Label 可以附加到各种资源上,一个资源对象可以定义任意数量的 Label,同一个 Label 也可以被添加到任意数量的资源上。

    我们可以通过给指定的资源对象捆绑一个或多个不同的 Label 来实现多维度的资源分组管理功能,以便于灵活、方便地进行资源分配、调度、配置、部署等工作。

    K8S 通过 Label Selector(标签选择器)来查询和筛选拥有某些 Label 的资源对象。Label Selector 有基于等式( name=label1 )和基于集合( name in (label1, label2) )的两种方式。

    3、ReplicaSet(RC)

    ReplicaSet 用来确保预期的 Pod 副本数量,如果有过多的 Pod 副本在运行,系统就会停掉一些 Pod,否则系统就会再自动创建一些 Pod。

    我们很少单独使用 ReplicaSet,它主要被 Deployment 这个更高层的资源对象使用,从而形成一整套 Pod 创建、删除、更新的编排机制。

    4、Deployment

    Deployment 用于部署无状态应用,Deployment 为 Pod 和 ReplicaSet 提供声明式更新,只需要在 Deployment 描述想要的目标状态,Deployment 就会将 Pod 和 ReplicaSet 的实际状态改变到目标状态。

    5、Horizontal Pod Autoscaler(HPA)

    HPA 为 Pod 横向自动扩容,也是 K8S 的一种资源对象。HPA 通过追踪分析 RC 的所有目标 Pod 的负载变化情况,来确定是否需要针对性调整目标 Pod 的副本数量。

    6、Service

    Service 定义了一个服务的访问入口,通过 Label Selector 与 Pod 副本集群之间“无缝对接”,定义了一组 Pod 的访问策略,防止 Pod 失联。

    创建 Service 时,K8S会自动为它分配一个全局唯一的虚拟 IP 地址,即 Cluster IP。服务发现就是通过 Service 的 Name 和 Service 的 ClusterIP 地址做一个 DNS 域名映射来解决的。

    7、Namespace

    命名空间,Namespace 多用于实现多租户的资源隔离。Namespace 通过将集群内部的资源对象“分配”到不同的Namespace中,形成逻辑上分组的不同项目、小组或用户组。

    K8S 集群在启动后,会创建一个名为 default 的 Namespace,如果不特别指明 Namespace,创建的 Pod、RC、Service 都将被创建到 default 下。

    当我们给每个租户创建一个 Namespace 来实现多租户的资源隔离时,还可以结合 K8S 的资源配额管理,限定不同租户能占用的资源,例如 CPU 使用量、内存使用量等。

    四、集群搭建 —— 平台规划

    1、生产环境 K8S 平台规划

    K8S 环境有两种架构方式,单 Master 集群和多 Master 集群,将先搭建起单 Master 集群,再扩展为多 Master 集群。开发、测试环境可以部署单 Master 集群,生产环境为了保证高可用需部署多 Master 集群。

    ① 单 Master 集群架构

    单 Master 集群架构相比于多 Master 集群架构无法保证集群的高可用,因为 master 节点一旦宕机就无法进行集群的管理工作了。单 master 集群主要包含一台 Master 节点,及多个 Node 工作节点、多个 Etcd 数据库节点。

    Etcd 是 K8S 集群的数据库,可以安装在任何地方,也可以与 Master 节点在同一台机器上,只要 K8S 能连通 Etcd。


    ② 多 Master 集群架构

    多 Master 集群能保证集群的高可用,相比单 Master 架构,需要一个额外的负载均衡器来负载多个 Master 节点,Node 节点从连接 Master 改成连接 LB 负载均衡器


    ③ 集群规划

    角色 IP 主机 组件
    k8s-master-1 192.168.137.14 k8s-master-1 kube-apiserver,kube-controller-manager,kube-scheduler,etcd
    k8s-master-1 192.168.137.15 k8s-master-2 kube-apiserver,kube-controller-manager,kube-scheduler
    k8s-node-1 192.168.137.16 k8s-node-1 kubelet,kube-proxy,docker,etcd
    k8s-node-1 192.168.137.17 k8s-node-2 kubelet,kube-proxy,docker,etcd
    Load Balancer(master) 192.168.137.18 k8s-lb-master Nginx L4
    Load Balancer(backup) 192.168.137.19 k8s-lb-backup Nginx L4

    ④ 服务器硬件配置推荐

    测试环境与生产环境服务器配置推荐如下,本地虚拟机的配置将按照本地测试环境的配置来创建虚拟机。


    2、操作系统初始化

    接下来将基于二进制包的方式,手动部署每个组件,来组成 K8S 高可用集群。通过手动部署每个组件,一步步熟悉每个组件的配置、组件之间的通信等,深层次的理解和掌握 K8S。

    首先做的是每台服务器的配置初始化,依次按如下步骤初始化。

    ① 关闭防火墙

    systemctl stop firewalld
    systemctl disable firewalld
    

    ② 关闭 selinux
    临时生效 setenforce 0,永久生效 sed -i 's/enforcing/disabled/' /etc/selinux/config

    ③ 关闭 swap
    临时关闭 swapoff -a
    永久生效

    vim /etc/fstab
    #将 [/dev/mapper/centos-swap swap                    swap    defaults        0 0] 这一行注释掉
    

    ④ 添加 hosts

    vim /etc/hosts
    
    192.168.137.14 k8s-master-1
    192.168.137.15 k8s-master-2
    192.168.137.16 k8s-node-1
    192.168.137.17 k8s-node-2
    192.168.137.18 k8s-lb-master
    192.168.137.19 k8s-lb-backup
    

    ⑤ 同步系统时间
    各个节点之间需保持时间一致,因为自签证书是根据时间校验证书有效性,如果时间不一致,将校验不通过。

    # #联网情况可使用如下命令
    # ntpdate time.windows.com
    
    # #如果不能联外网可使用 date 命令设置时间
    

    五、集群搭建 —— 部署Etcd集群

    1、自签证书

    K8S 集群安装配置过程中,会使用各种证书,目的是为了加强集群安全性。K8S 提供了基于 CA 签名的双向数字证书认证方式和简单的基于 http base 或 token 的认证方式,其中 CA 证书方式的安全性最高。每个K8S集群都有一个集群根证书颁发机构(CA),集群中的组件通常使用CA来验证API server的证书,由API服务器验证kubelet客户端证书等。

    证书生成操作可以在master节点上执行,证书只需要创建一次,以后在向集群中添加新节点时只要将证书拷贝到新节点上,并做一定的配置即可。下面就在 k8s-master-1 节点上来创建证书,详细的介绍也可以参考官方文档:分发自签名-CA-证书

    ① K8S 证书

    如下是 K8S 各个组件需要使用的证书


    ② 准备 cfssl 工具

    我是使用 cfssl 工具来生成证书,首先下载 cfssl 工具。依次执行如下命令:

    curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
    curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
    curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo
    
    chmod +x /usr/local/bin/cfssl*
    

    2、自签 Etcd SSL 证书

    我们首先为 etcd 签发一套SSL证书,通过如下命令创建几个目录,/k8s/etcd/ssl 用于存放 etcd 自签证书,/k8s/etcd/cfg 用于存放 etcd 配置文件,/k8s/etcd/bin 用于存放 etcd 执行程序。

    mkdir -p /k8s/etcd/{ssl,cfg,bin}
    

    进入 etcd 目录:

    cd /k8s/etcd/ssl
    

    ① 创建 CA 配置文件:ca-config.json

    执行如下命令创建 ca-config.json

    cat > ca-config.json <<EOF
    {
      "signing": {
        "default": {
          "expiry": "87600h"
        },
        "profiles": {
          "etcd": {
            "usages": [
                "signing",
                "key encipherment",
                "server auth",
                "client auth"
            ],
            "expiry": "87600h"
          }
        }
      }
    }
    EOF
    

    说明:

    • signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
    • profiles:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
    • expiry:证书过期时间
    • server auth:表示client可以用该 CA 对server提供的证书进行验证;
    • client auth:表示server可以用该CA对client提供的证书进行验证;

    ② 创建 CA 证书签名请求文件:ca-csr.json

    执行如下命令创建 ca-csr.json:

    cat > ca-csr.json <<EOF
    {
      "CN": "etcd",
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "Shanghai",
          "L": "Shanghai",
          "O": "etcd",
          "OU": "System"
        }
      ],
        "ca": {
           "expiry": "87600h"
        }
    }
    EOF
    

    说明:

    • CN:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
    • key:加密算法
    • C:国家
    • ST:地区
    • L:城市
    • O:组织,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
    • OU:组织单位

    ③ 生成 CA 证书和私钥

    [root@localhost ssl]# ll
    总用量 8
    -rw-r--r--. 1 root root 286 9月  17 21:34 ca-config.json
    -rw-r--r--. 1 root root 250 9月  17 21:36 ca-csr.json
    [root@localhost ssl]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
    2023/09/17 21:40:55 [INFO] generating a new CA key and certificate from CSR
    2023/09/17 21:40:55 [INFO] generate received request
    2023/09/17 21:40:55 [INFO] received CSR
    2023/09/17 21:40:55 [INFO] generating key: rsa-2048
    2023/09/17 21:40:55 [INFO] encoded CSR
    2023/09/17 21:40:55 [INFO] signed certificate with serial number 701481595761330401456406283469574221010089175792
    [root@localhost ssl]# ls
    ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem
    

    说明:

    • ca-key.pem:CA 私钥
    • ca.pem:CA 数字证书

    ④ 创建证书签名请求文件:etcd-csr.json
    执行如下命令创建 etcd-csr.json:

    cat > etcd-csr.json <<EOF
    {
        "CN": "etcd",
        "hosts": [
          "192.168.137.14",
          "192.168.137.16",
          "192.168.137.17"
        ],
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "ST": "BeiJing",
                "L": "BeiJing",
                "O": "etcd",
                "OU": "System"
            }
        ]
    }
    EOF
    

    说明:

    • hosts:需要指定授权使用该证书的 IP 或域名列表,这里配置所有 etcd 的IP地址。
    • key:加密算法及长度

    ⑤ 为 etcd 生成证书和私钥

    [root@localhost ssl]# ls
    ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  etcd-csr.json
    [root@localhost ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd etcd-csr.json | cfssljson -bare etcd
    2023/09/17 21:46:49 [INFO] generate received request
    2023/09/17 21:46:49 [INFO] received CSR
    2023/09/17 21:46:49 [INFO] generating key: rsa-2048
    2023/09/17 21:46:49 [INFO] encoded CSR
    2023/09/17 21:46:49 [INFO] signed certificate with serial number 350599829265555004142693609766831172405337534555
    2023/09/17 21:46:49 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
    websites. For more information see the Baseline Requirements for the Issuance and Management
    of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
    specifically, section 10.2.3 ("Information Requirements").
    [root@localhost ssl]# ls
    ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  etcd.csr  etcd-csr.json  etcd-key.pem  etcd.pem
    

    参数说明:

    • ca:指定 CA 数字证书
    • ca-key:指定 CA 私钥
    • config:CA 配置文件
    • profile:指定环境
    • bare:指定证书名前缀

    文件说明:

    • etcd-key.pem:etcd 私钥
    • etcd.pem:etcd 数字证书

    证书生成完成,后面部署 Etcd 时主要会用到如下几个证书:

    [root@localhost ssl]# pwd
    /k8s/etcd/ssl
    [root@localhost ssl]# ls *.pem
    ca-key.pem  ca.pem  etcd-key.pem  etcd.pem
    

    3、Etcd 数据库集群部署
    etcd 集群采用主从架构模式(一主多从)部署,集群通过选举产生 leader,因此需要部署奇数个节点(3/5/7)才能正常工作。etcd使用raft一致性算法保证每个节点的一致性。

    ① 下载 etcd

    从 github 上下载合适版本的 etcd

    cd /k8s/etcd
    wget https://github.com/coreos/etcd/releases/download/v3.5.0/etcd-v3.5.0-linux-amd64.tar.gz
    

    解压:

    tar zxf etcd-v3.5.0-linux-amd64.tar.gz
    

    将 etcd 复制到 /usr/local/bin 下:

    cp etcd-v3.5.0-linux-amd64/{etcd,etcdctl} /k8s/etcd/bin
    rm -rf etcd-v3.5.0-linux-amd64*
    

    ② 创建 etcd 配置文件:etcd.conf

    cat > /k8s/etcd/cfg/etcd.conf <<EOF 
    # [member]
    ETCD_NAME=etcd-1
    ETCD_DATA_DIR=/k8s/data/default.etcd
    ETCD_LISTEN_PEER_URLS=https://192.168.137.14:2380
    ETCD_LISTEN_CLIENT_URLS=https://192.168.137.14:2379
    
    # [cluster]
    ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.137.14:2380
    ETCD_ADVERTISE_CLIENT_URLS=https://192.168.137.14:2379
    ETCD_INITIAL_CLUSTER=etcd-1=https://192.168.137.14:2380,etcd-2=https://192.168.137.16:2380,etcd-3=https://192.168.137.17:2380
    ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
    ETCD_INITIAL_CLUSTER_STATE=new
    
    # [security]
    ETCD_CERT_FILE=/k8s/etcd/ssl/etcd.pem
    ETCD_KEY_FILE=/k8s/etcd/ssl/etcd-key.pem
    ETCD_TRUSTED_CA_FILE=/k8s/etcd/ssl/ca.pem
    ETCD_PEER_CERT_FILE=/k8s/etcd/ssl/etcd.pem
    ETCD_PEER_KEY_FILE=/k8s/etcd/ssl/etcd-key.pem
    ETCD_PEER_TRUSTED_CA_FILE=/k8s/etcd/ssl/ca.pem
    EOF
    

    说明:

    • ETCD_NAME:etcd在集群中的唯一名称
    • ETCD_DATA_DIR:etcd数据存放目录
    • ETCD_LISTEN_PEER_URLS:etcd集群间通讯的地址,设置为本机IP
    • ETCD_LISTEN_CLIENT_URLS:客户端访问的地址,设置为本机IP
    • ETCD_INITIAL_ADVERTISE_PEER_URLS:初始集群通告地址,集群内部通讯地址,设置为本机IP
    • ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址,设置为本机IP
    • ETCD_INITIAL_CLUSTER:集群节点地址,以 key=value 的形式添加各个 etcd 的地址
    • ETCD_INITIAL_CLUSTER_TOKEN:集群令牌,用于集群间做简单的认证
    • ETCD_INITIAL_CLUSTER_STATE:集群状态
    • ETCD_CERT_FILE:客户端 etcd 数字证书路径
    • ETCD_KEY_FILE:客户端 etcd 私钥路径
    • ETCD_TRUSTED_CA_FILE:客户端 CA 证书路径
    • ETCD_PEER_CERT_FILE:集群间通讯etcd数字证书路径
    • ETCD_PEER_KEY_FILE:集群间通讯etcd私钥路径
    • ETCD_PEER_TRUSTED_CA_FILE:集群间通讯CA证书路径
      ③ 创建 etcd 服务:etcd.service

    通过EnvironmentFile指定 etcd.conf 作为环境配置文件

    cat > /k8s/etcd/etcd.service <<'EOF'
    [Unit]
    Description=Etcd Server
    After=network.target
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=notify
    EnvironmentFile=/k8s/etcd/cfg/etcd.conf
    WorkingDirectory=${ETCD_DATA_DIR}
    
    ExecStart=/k8s/etcd/bin/etcd \
      --name=${ETCD_NAME} \
      --data-dir=${ETCD_DATA_DIR} \
      --listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \
      --listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379 \
      --initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
      --advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \
      --initial-cluster=${ETCD_INITIAL_CLUSTER} \
      --initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \
      --initial-cluster-state=${ETCD_INITIAL_CLUSTER_STATE} \
      --cert-file=${ETCD_CERT_FILE} \
      --key-file=${ETCD_KEY_FILE} \
      --trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
      --peer-cert-file=${ETCD_PEER_CERT_FILE} \
      --peer-key-file=${ETCD_PEER_KEY_FILE} \
      --peer-trusted-ca-file=${ETCD_PEER_TRUSTED_CA_FILE}
    
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    etcd.service 更多的配置以及说明可以通过如下命令查看:/k8s/etcd/bin/etcd --help

    ETCD3.4版本会自动读取环境变量的参数,所以EnvironmentFile文件中有的参数,不需要再次在ExecStart启动参数中添加,二选一,如同时配置,会触发以下类似报错

    etcd: conflicting environment variable "ETCD_NAME" is shadowed by corresponding command-line flag (either unset environment variable or disable flag)
    

    ④ 将 etcd 目录拷贝到另外两个节点

    [root@localhost etcd]# scp -r /k8s/ root@k8s-node-1:/k8s
    The authenticity of host 'k8s-node-1 (192.168.137.16)' can't be established.
    ECDSA key fingerprint is SHA256:8NHw5kqsFAXGzdOH4LTN6v9ps+Bl3C9k9sEUf6ZEfVw.
    ECDSA key fingerprint is MD5:57:b3:24:da:12:ad:bb:37:23:12:57:6f:d0:87:0f:58.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'k8s-node-1,192.168.137.16' (ECDSA) to the list of known hosts.
    root@k8s-node-1's password: 
    ca-config.json                                                                                                                                                                                                                              100%  286   680.0KB/s   00:00    
    ca-csr.json                                                                                                                                                                                                                                 100%  250   504.9KB/s   00:00    
    ca.pem                                                                                                                                                                                                                                      100% 1350     3.0MB/s   00:00    
    ca-key.pem                                                                                                                                                                                                                                  100% 1679     4.0MB/s   00:00    
    ca.csr                                                                                                                                                                                                                                      100%  997     2.6MB/s   00:00    
    etcd-csr.json                                                                                                                                                                                                                               100%  352   930.6KB/s   00:00    
    etcd.pem                                                                                                                                                                                                                                    100% 1424     3.0MB/s   00:00    
    etcd-key.pem                                                                                                                                                                                                                                100% 1675     4.1MB/s   00:00    
    etcd.csr                                                                                                                                                                                                                                    100% 1058     2.7MB/s   00:00    
    etcd.conf                                                                                                                                                                                                                                   100%  764     2.0MB/s   00:00    
    etcd                                                                                                                                                                                                                                        100%   22MB 256.0MB/s   00:00    
    etcdctl                                                                                                                                                                                                                                     100%   17MB 262.4MB/s   00:00    
    etcd.service                                                                                                                                                                                                                                100% 1033     3.0MB/s   00:00    
    [root@localhost etcd]# scp -r /k8s/ root@k8s-node-2:/k8s
    The authenticity of host 'k8s-node-2 (192.168.137.17)' can't be established.
    ECDSA key fingerprint is SHA256:zdJng7VI65mj43rSyJ+/FhSxmlI07PTpWTG8H5JDsAI.
    ECDSA key fingerprint is MD5:f4:87:57:e4:91:de:8a:9d:16:83:50:7e:03:ca:2d:4e.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'k8s-node-2,192.168.137.17' (ECDSA) to the list of known hosts.
    root@k8s-node-2's password: 
    ca-config.json                                                                                                                                                                                                                              100%  286   480.1KB/s   00:00    
    ca-csr.json                                                                                                                                                                                                                                 100%  250   578.8KB/s   00:00    
    ca.pem                                                                                                                                                                                                                                      100% 1350     3.3MB/s   00:00    
    ca-key.pem                                                                                                                                                                                                                                  100% 1679     4.0MB/s   00:00    
    ca.csr                                                                                                                                                                                                                                      100%  997     2.1MB/s   00:00    
    etcd-csr.json                                                                                                                                                                                                                               100%  352     1.0MB/s   00:00    
    etcd.pem                                                                                                                                                                                                                                    100% 1424     3.2MB/s   00:00    
    etcd-key.pem                                                                                                                                                                                                                                100% 1675     4.8MB/s   00:00    
    etcd.csr                                                                                                                                                                                                                                    100% 1058     2.7MB/s   00:00    
    etcd.conf                                                                                                                                                                                                                                   100%  764     2.0MB/s   00:00    
    etcd                                                                                                                                                                                                                                        100%   22MB 242.6MB/s   00:00    
    etcdctl                                                                                                                                                                                                                                     100%   17MB 262.6MB/s   00:00    
    etcd.service
    

    ⑤ 修改两个节点配置文件

    修改 k8s-node-1 节点的 /k8s/etcd/cfg/etcd.conf:

    # [member]
    ETCD_NAME=etcd-2
    ETCD_LISTEN_PEER_URLS=https://192.168.31.35:2380
    ETCD_LISTEN_CLIENT_URLS=https://192.168.31.35:2379
    
    # [cluster]
    ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.31.35:2380
    ETCD_ADVERTISE_CLIENT_URLS=https://192.168.31.35:2379
    

    修改 k8s-node-2 节点的 /k8s/etcd/cfg/etcd.conf:

    # [member]
    ETCD_NAME=etcd-3
    ETCD_LISTEN_PEER_URLS=https://192.168.31.71:2380
    ETCD_LISTEN_CLIENT_URLS=https://192.168.31.71:2379
    
    # [cluster]
    ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.31.71:2380
    ETCD_ADVERTISE_CLIENT_URLS=https://192.168.31.71:2379
    

    ⑥ 启动 etcd 服务
    首先在三个节点将 etcd.service 拷贝到 /usr/lib/systemd/system/ 下

    cp /k8s/etcd/etcd.service /usr/lib/systemd/system/
    systemctl daemon-reload
    

    在三个节点启动 etcd 服务 systemctl start etcd
    设置开机启动 systemctl enable etcd
    查看 etcd 的日志 tail -f /var/log/messages

    注意:如果日志中出现连接异常信息,请确认所有节点防火墙是否开放2379,2380端口,或者直接关闭防火墙。
    查看 etcd 集群状态

    /k8s/etcd/bin/etcdctl \
        --cacert=/k8s/etcd/ssl/ca.pem \
        --key=/k8s/etcd/ssl/etcd-key.pem \
        --cert=/k8s/etcd/ssl/etcd.pem \
        --endpoints=https://192.168.137.14:2379,https://192.168.137.16:2379,https://192.168.137.17:2379 \
        --write-out=table \
    endpoint health 
    

    执行结果

    [root@localhost etcd]# /k8s/etcd/bin/etcdctl \
    >     --cacert=/k8s/etcd/ssl/ca.pem \
    >     --key=/k8s/etcd/ssl/etcd-key.pem \
    >     --cert=/k8s/etcd/ssl/etcd.pem \
    >     --endpoints=https://192.168.137.14:2379,https://192.168.137.16:2379,https://192.168.137.17:2379 \
    >     --write-out=table \
    > endpoint health 
    +-----------------------------+--------+-------------+-------+
    |          ENDPOINT           | HEALTH |    TOOK     | ERROR |
    +-----------------------------+--------+-------------+-------+
    | https://192.168.137.14:2379 |   true |   6.79061ms |       |
    | https://192.168.137.17:2379 |   true | 11.304482ms |       |
    | https://192.168.137.16:2379 |   true | 11.374983ms |       |
    +-----------------------------+--------+-------------+-------+
    

    六、集群搭建 —— 部署Master组件

    1、自签 ApiServer SSL 证书

    K8S 集群中所有资源的访问和变更都是通过 kube-apiserver 的 REST API 来实现的,首先在 master 节点上部署 kube-apiserver 组件。

    我们首先为 apiserver 签发一套SSL证书,过程与 etcd 自签SSL证书类似。通过如下命令创建几个目录,ssl 用于存放自签证书,cfg 用于存放配置文件,bin 用于存放执行程序,logs 存放日志文件。

    mkdir -p /k8s/kubernetes/{ssl,cfg,bin,logs}
    

    进入 kubernetes 目录:

    cd /k8s/kubernetes/ssl
    

    ① 创建 CA 配置文件:ca-config.json

    执行如下命令创建 ca-config.json

    cat > ca-config.json <<EOF
    {
      "signing": {
        "default": {
          "expiry": "87600h"
        },
        "profiles": {
          "kubernetes": {
            "usages": [
                "signing",
                "key encipherment",
                "server auth",
                "client auth"
            ],
            "expiry": "87600h"
          }
        }
      }
    }
    EOF
    

    ② 创建 CA 证书签名请求文件:ca-csr.json

    执行如下命令创建 ca-csr.json:

    cat > ca-csr.json <<EOF
    {
      "CN": "kubernetes",
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "Shanghai",
          "L": "Shanghai",
          "O": "kubernetes",
          "OU": "System"
        }
      ],
        "ca": {
           "expiry": "87600h"
        }
    }
    EOF
    

    ③ 生成 CA 证书和私钥

    cfssl gencert -initca ca-csr.json | cfssljson -bare ca
    

    ④ 创建证书签名请求文件:kubernetes-csr.json

    执行如下命令创建 kubernetes-csr.json:

    cat > kubernetes-csr.json <<EOF
    {
        "CN": "kubernetes",
        "hosts": [
          "127.0.0.1",
          "10.0.0.1",
          "192.168.137.14",
          "192.168.137.15",
          "192.168.137.16",
          "192.168.137.17",
          "kubernetes",
          "kubernetes.default",
          "kubernetes.default.svc",
          "kubernetes.default.svc.cluster",
          "kubernetes.default.svc.cluster.local"
        ],
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "ST": "BeiJing",
                "L": "BeiJing",
                "O": "kubernetes",
                "OU": "System"
            }
        ]
    }
    EOF
    

    说明:

    • hosts:指定会直接访问 apiserver 的IP列表,一般需指定 etcd 集群、kubernetes master 集群的主机 IP 和 kubernetes 服务的服务 IP,Node 的IP一般不需要加入。

    ⑤ 为 kubernetes 生成证书和私钥

    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
    

    2、部署 kube-apiserver 组件

    ① 下载二进制包

    通过 kubernetes Github 下载安装用的二进制包,server 二进制包已经包含了 master、node 上的各个组件,下载 server 二进制包即可。

    cd /data/soft
    wget https://dl.k8s.io/v1.16.2/kubernetes-server-linux-amd64.tar.gz --no-check-certificate
    

    解压:

    tar -zxf kubernetes-server-linux-amd64.tar.gz
    

    先将 master 节点上部署的组件拷贝到 /k8s/kubernetes/bin 目录下:

    cp -p /data/soft/kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler} /k8s/kubernetes/bin/
    cp -p /data/soft/kubernetes/server/bin/kubectl /usr/local/bin/
    

    ② 创建 Node 令牌文件:token.csv
    Master apiserver 启用 TLS 认证后,Node节点 kubelet 组件想要加入集群,必须使用CA签发的有效证书才能与apiserver通信,当Node节点很多时,签署证书是一件很繁琐的事情,因此有了 TLS Bootstrap 机制,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。因此先为 apiserver 生成一个令牌文件,令牌之后会在 Node 中用到。

    生成 token,一个随机字符串,可使用如下命令生成 token:apiserver 配置的 token 必须与 Node 节点 bootstrap.kubeconfig 配置保持一致。

    [root@k8s-master-1 kubernetes]# head -c 16 /dev/urandom | od -An -t x | tr -d ' '
    b9187da74c444ee060a1c6053eab97c7
    

    创建 token.csv,格式:token,用户,UID,用户组

    cat > /k8s/kubernetes/cfg/token.csv <<'EOF'
    b9187da74c444ee060a1c6053eab97c7,kubelet-bootstrap,10001,"system:node-bootstrapper"
    EOF
    

    ③ 创建 kube-apiserver 配置文件:kube-apiserver.conf

    kube-apiserver 有很多配置项,可以参考官方文档查看每个配置项的用途:kube-apiserver

    注意:踩的一个坑,“\” 后面不要有空格,不要有多余的换行,否则启动失败。

    cat > /k8s/kubernetes/cfg/kube-apiserver.conf <<'EOF'
    KUBE_APISERVER_OPTS="--etcd-servers=https://192.168.137.14:2379,https://192.168.137.16:2379,https://192.168.137.17:2379 \
      --bind-address=192.168.137.14 \
      --secure-port=6443 \
      --advertise-address=192.168.137.14 \
      --allow-privileged=true \
      --service-cluster-ip-range=10.0.0.0/24 \
      --service-node-port-range=30000-32767 \
      --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
      --authorization-mode=RBAC,Node \
      --enable-bootstrap-token-auth=true \
      --token-auth-file=/k8s/kubernetes/cfg/token.csv \
      --kubelet-client-certificate=/k8s/kubernetes/ssl/kubernetes.pem \
      --kubelet-client-key=/k8s/kubernetes/ssl/kubernetes-key.pem \
      --tls-cert-file=/k8s/kubernetes/ssl/kubernetes.pem \
      --tls-private-key-file=/k8s/kubernetes/ssl/kubernetes-key.pem \
      --client-ca-file=/k8s/kubernetes/ssl/ca.pem \
      --service-account-key-file=/k8s/kubernetes/ssl/ca-key.pem \
      --service-account-signing-key-file=/k8s/kubernetes/ssl/kubernetes-key.pem \
      --service-account-issuer=https://kubernetes.service.account.issuer \
      --etcd-cafile=/k8s/etcd/ssl/ca.pem \
      --etcd-certfile=/k8s/etcd/ssl/etcd.pem \
      --etcd-keyfile=/k8s/etcd/ssl/etcd-key.pem \
      --v=2 \
      --logtostderr=false \
      --log-dir=/k8s/kubernetes/logs \
      --audit-log-maxage=30 \
      --audit-log-maxbackup=3 \
      --audit-log-maxsize=100 \
      --audit-log-path=/k8s/kubernetes/logs/k8s-audit.log"
    EOF
    

    重点配置说明:

    • --etcd-servers:etcd 集群地址
    • --bind-address:apiserver 监听的地址,一般配主机IP
    • --secure-port:监听的端口
    • --advertise-address:集群通告地址,其它Node节点通过这个地址连接 apiserver,不配置则使用 --bind-address
    • --service-cluster-ip-range:Service 的 虚拟IP范围,以CIDR格式标识,该IP范围不能与物理机的真实IP段有重合。
    • --service-node-port-range:Service 可映射的物理机端口范围,默认30000-32767
    • --admission-control:集群的准入控制设置,各控制模块以插件的形式依次生效,启用RBAC授权和节点自管理
    • --authorization-mode:授权模式,包括:AlwaysAllow,AlwaysDeny,ABAC(基于属性的访问控制),Webhook,RBAC(基于角色的访问控制),Node(专门授权由 kubelet 发出的API请求)。(默认值"AlwaysAllow")。
    • --enable-bootstrap-token-auth:启用TLS bootstrap功能
    • --token-auth-file:这个文件将被用于通过令牌认证来保护API服务的安全端口。
    • --v:指定日志级别,0~8,越大日志越详细

    ④ 创建 apiserver 服务:kube-apiserver.service

    cat > /usr/lib/systemd/system/kube-apiserver.service <<'EOF'
    [Unit]
    Description=Kubernetes API Server
    Documentation=https://github.com/GoogleCloudPlatform/kubernetes
    After=network.target
    
    [Service]
    EnvironmentFile=/k8s/kubernetes/cfg/kube-apiserver.conf
    ExecStart=/k8s/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
    
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    ⑤ 启动 kube-apiserver 组件
    启动组件

    systemctl daemon-reload
    systemctl start kube-apiserver
    systemctl enable kube-apiserver
    

    检查启动状态

    systemctl status kube-apiserver.service
    

    查看启动日志

    less /k8s/kubernetes/logs/kube-apiserver.INFO
    

    ⑥ 将 kubelet-bootstrap 用户绑定到系统集群角色,之后便于 Node 使用token请求证书

    kubectl create clusterrolebinding kubelet-bootstrap \
      --clusterrole=system:node-bootstrapper \
      --user=kubelet-bootstrap
    

    3、部署 kube-controller-manager 组件

    ① 创建 kube-controller-manager 配置文件:kube-controller-manager.conf

    详细的配置可参考官方文档:kube-controller-manager

    cat > /k8s/kubernetes/cfg/kube-controller-manager.conf <<'EOF'
    KUBE_CONTROLLER_MANAGER_OPTS="--leader-elect=true \
      --master=127.0.0.1:8080 \
      --address=127.0.0.1 \
      --allocate-node-cidrs=true \
      --cluster-cidr=10.244.0.0/16 \
      --service-cluster-ip-range=10.0.0.0/24 \
      --cluster-signing-cert-file=/k8s/kubernetes/ssl/ca.pem \
      --cluster-signing-key-file=/k8s/kubernetes/ssl/ca-key.pem \
      --root-ca-file=/k8s/kubernetes/ssl/ca.pem \
      --service-account-private-key-file=/k8s/kubernetes/ssl/ca-key.pem \
      --experimental-cluster-signing-duration=87600h0m0s \
      --v=2 \
      --logtostderr=false \
      --log-dir=/k8s/kubernetes/logs"
    EOF
    

    重点配置说明:

    • --leader-elect:当该组件启动多个时,自动选举,默认true
    • --master:连接本地apiserver,apiserver 默认会监听本地8080端口
    • --allocate-node-cidrs:是否分配和设置Pod的CDIR
    • --service-cluster-ip-range:Service 集群IP段
      ② 创建 kube-controller-manager 服务:kube-controller-manager.service
    cat > /usr/lib/systemd/system/kube-controller-manager.service <<'EOF'
    [Unit]
    Description=Kubernetes Controller Manager
    Documentation=https://github.com/GoogleCloudPlatform/kubernetes
    After=network.target
    
    [Service]
    EnvironmentFile=/k8s/kubernetes/cfg/kube-controller-manager.conf
    ExecStart=/k8s/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
    
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    ③ 启动 kube-controller-manager 组件

    启动组件

    systemctl daemon-reload
    systemctl start kube-controller-manager
    systemctl enable kube-controller-manager
    

    4、部署 kube-scheduler 组件
    ① 创建 kube-scheduler 配置文件:kube-scheduler.conf

    cat > /k8s/kubernetes/cfg/kube-scheduler.conf <<'EOF'
    KUBE_SCHEDULER_OPTS="--leader-elect=true \
      --master=127.0.0.1:8080 \
      --address=127.0.0.1 \
      --v=2 \
      --logtostderr=false \
      --log-dir=/k8s/kubernetes/logs"
    EOF
    

    ② 创建 kube-scheduler 服务:kube-scheduler.service

    cat > /usr/lib/systemd/system/kube-scheduler.service <<'EOF'
    [Unit]
    Description=Kubernetes Scheduler
    Documentation=https://github.com/GoogleCloudPlatform/kubernetes
    After=network.target
    
    [Service]
    EnvironmentFile=/k8s/kubernetes/cfg/kube-scheduler.conf
    ExecStart=/k8s/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
    
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    ③ 启动 kube-scheduler 组件

    启动组件

    systemctl daemon-reload
    systemctl start kube-scheduler
    systemctl enable kube-scheduler
    

    查看启动状态

    systemctl status kube-scheduler.service
    

    查看启动日志

    less /k8s/kubernetes/logs/kube-scheduler.INFO
    

    5、查看集群状态
    ① 查看组件状态

    kubectl get cs
    

    七、集群搭建 —— 部署Node组件

    1、安装 Docker

    CentOS 安装参考官方文档:https://docs.docker.com/install/linux/docker-ce/centos/
    k8s-node-1,k8s-node-2 安装docker
    ① 卸载旧版本

    yum remove docker docker-common docker-selinux
    

    ② 安装依赖包

    yum install -y yum-utils device-mapper-persistent-data lvm2
    

    ③ 安装 Docker 软件包源

    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    

    ④ 安装 Docker CE

    yum install docker-ce
    

    ⑤ 启动 Docker 服务

    systemctl start docker
    

    ⑥ 设置开机启动

    systemctl enable docker
    

    ⑦ 验证安装是否成功

    docker -v
    docker info
    

    2、Node 节点证书

    ① 创建 Node 节点的证书签名请求文件:kube-proxy-csr.json

    首先在 k8s-master-1 节点上,通过颁发的 CA 证书先创建好 Node 节点要使用的证书,先创建证书签名请求文件:kube-proxy-csr.json:

    cat > /k8s/kubernetes/ssl/kube-proxy-csr.json <<EOF
    {
        "CN": "system:kube-proxy",
        "hosts": [],
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "ST": "BeiJing",
                "L": "BeiJing",
                "O": "kubernetes",
                "OU": "System"
            }
        ]
    }
    EOF
    

    ② 为 kube-proxy 生成证书和私钥

    cd /k8s/kubernetes/ssl
    
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
    

    ③ node 节点创建工作目录

    在 k8s-node-1 节点上创建 k8s 目录

    mkdir -p /k8s/kubernetes/{bin,cfg,logs,ssl}
    

    ④ 将 k8s-master-1 节点的文件拷贝到 node 节点

    将 kubelet、kube-proxy 拷贝到 node 节点上:

    scp -r /data/soft/kubernetes/server/bin/{kubelet,kube-proxy} root@k8s-node-1:/k8s/kubernetes/bin/
    

    将证书拷贝到 k8s-node-1 节点上:

    scp -r /k8s/kubernetes/ssl/{ca.pem,kube-proxy.pem,kube-proxy-key.pem} root@k8s-node-1:/k8s/kubernetes/ssl/
    

    3、安装 kubelet

    ① 创建请求证书的配置文件:bootstrap.kubeconfig

    bootstrap.kubeconfig 将用于向 apiserver 请求证书,apiserver 会验证 token、证书 是否有效,验证通过则自动颁发证书。

    cat > /k8s/kubernetes/cfg/bootstrap.kubeconfig <<'EOF'
    apiVersion: v1
    clusters:
    - cluster: 
        certificate-authority: /k8s/kubernetes/ssl/ca.pem
        server: https://192.168.137.14:6443
      name: kubernetes
    contexts:
    - context:
        cluster: kubernetes
        user: kubelet-bootstrap
      name: default
    current-context: default
    kind: Config
    preferences: {}
    users:
    - name: kubelet-bootstrap
      user:
        token: b9187da74c444ee060a1c6053eab97c7
    EOF
    

    说明:

    • certificate-authority:CA 证书
    • server:master 地址
    • token:master 上 token.csv 中配置的 token

    ② 创建 kubelet 配置文件:kubelet-config.yml

    为了安全性,kubelet 禁止匿名访问,必须授权才可以,通过 kubelet-config.yml 授权 apiserver 访问 kubelet。

    cat > /k8s/kubernetes/cfg/kubelet-config.yml <<'EOF'
    kind: KubeletConfiguration
    apiVersion: kubelet.config.k8s.io/v1beta1
    address: 0.0.0.0
    port: 10250
    readOnlyPort: 10255
    cgroupDriver: cgroupfs
    clusterDNS:
    - 10.0.0.2 
    clusterDomain: cluster.local
    failSwapOn: false
    authentication:
      anonymous:
        enabled: false
      webhook:
        cacheTTL: 2m0s
        enabled: true
      x509: 
        clientCAFile: /k8s/kubernetes/ssl/ca.pem
    authorization:
      mode: Webhook
      webhook:
        cacheAuthroizedTTL: 5m0s
        cacheUnauthorizedTTL: 30s
    evictionHard:
      imagefs.available: 15%
      memory.available: 100Mi
      nodefs.available: 10%
      nodefs.inodesFree: 5%
    maxOpenFiles: 100000
    maxPods: 110
    EOF
    

    说明:

    • address:kubelet 监听地址
    • port:kubelet 的端口
    • cgroupDriver:cgroup 驱动,与 docker 的 cgroup 驱动一致
    • authentication:访问 kubelet 的授权信息
    • authorization:认证相关信息
    • evictionHard:垃圾回收策略
    • maxPods:最大pod数

    ③ 创建 kubelet 服务配置文件:kubelet.conf

    cat > /k8s/kubernetes/cfg/kubelet.conf <<'EOF'
    KUBELET_OPTS="--hostname-override=k8s-node-1 \
      --network-plugin=cni \
      --cni-bin-dir=/opt/cni/bin \
      --cni-conf-dir=/etc/cni/net.d \
      --cgroups-per-qos=false \
      --enforce-node-allocatable="" \
      --kubeconfig=/k8s/kubernetes/cfg/kubelet.kubeconfig \
      --bootstrap-kubeconfig=/k8s/kubernetes/cfg/bootstrap.kubeconfig \
      --config=/k8s/kubernetes/cfg/kubelet-config.yml \
      --cert-dir=/k8s/kubernetes/ssl \
      --pod-infra-container-image=kubernetes/pause:latest \
      --v=2 \
      --logtostderr=false \
      --log-dir=/k8s/kubernetes/logs"
    EOF
    

    说明:

    • --hostname-override:当前节点注册到K8S中显示的名称,默认为主机 hostname
    • --network-plugin:启用 CNI 网络插件
    • --cni-bin-dir:CNI 插件可执行文件位置,默认在 /opt/cni/bin 下
    • --cni-conf-dir:CNI 插件配置文件位置,默认在 /etc/cni/net.d 下
    • --cgroups-per-qos:必须加上这个参数和--enforce-node-allocatable,否则报错 [Failed to start ContainerManager failed to initialize top level QOS containers.......]
    • --kubeconfig:会自动生成 kubelet.kubeconfig,用于连接 apiserver
    • --bootstrap-kubeconfig:指定 bootstrap.kubeconfig 文件
    • --config:kubelet 配置文件
    • --cert-dir:证书目录
    • --pod-infra-container-image:管理Pod网络的镜像,基础的 Pause 容器,默认是 k8s.gcr.io/pause:3.1

    ④ 创建 kubelet 服务:kubelet.service

    cat > /usr/lib/systemd/system/kubelet.service <<'EOF'
    [Unit]
    Description=Kubernetes Kubelet
    After=docker.service
    Before=docker.service
    
    [Service]
    EnvironmentFile=/k8s/kubernetes/cfg/kubelet.conf
    ExecStart=/k8s/kubernetes/bin/kubelet $KUBELET_OPTS
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    ⑤ 启动 kubelet

    systemctl daemon-reload
    systemctl start kubelet
    

    开机启动:

    systemctl enable kubelet
    

    查看启动日志:

    tail -f /k8s/kubernetes/logs/kubelet.INFO
    

    ⑥ master 给 node 授权

    kubelet 启动后,还没加入到集群中,会向 apiserver 请求证书,需手动在 k8s-master-1 上对 node 授权。

    通过如下命令查看是否有新的客户端请求颁发证书:

    [root@k8s-master-1 ssl]# kubectl get csr
    NAME                                                   AGE   REQUESTOR           CONDITION
    node-csr-6jk-QVHhy1BdMfqAZ6znhkgmFocCk69nSozPR59QBMI   60s   kubelet-bootstrap   Pending
    

    给客户端颁发证书,允许客户端加入集群:

    [root@k8s-master-1 ssl]# kubectl certificate approve node-csr-6jk-QVHhy1BdMfqAZ6znhkgmFocCk69nSozPR59QBMI
    certificatesigningrequest.certificates.k8s.io/node-csr-6jk-QVHhy1BdMfqAZ6znhkgmFocCk69nSozPR59QBMI approved
    

    ⑦ 授权成功

    查看 node 是否加入集群(此时的 node 还处于未就绪的状态,因为还没有安装 CNI 组件):

    [root@k8s-master-1 ssl]# kubectl get node
    NAME         STATUS     ROLES    AGE   VERSION
    k8s-node-1   NotReady   <none>   2s    v1.16.2
    

    颁发证书后,可以在 /k8s/kubenetes/ssl 下看到 master 为 kubelet 颁发的证书:

    [root@k8s-node-1 ~]# ls /k8s/kubernetes/ssl/
    ca.pem  kubelet-client-2023-09-18-17-15-25.pem  kubelet-client-current.pem  kubelet.crt  kubelet.key  kube-proxy-key.pem  kube-proxy.pem
    

    在 /k8s/kubenetes/cfg 下可以看到自动生成的 kubelet.kubeconfig 配置文件:

    [root@k8s-node-1 ~]# ls /k8s/kubernetes/cfg
    bootstrap.kubeconfig  kubelet.conf  kubelet-config.yml  kubelet.kubeconfig
    

    4、安装 kube-proxy

    ① 创建 kube-proxy 连接 apiserver 的配置文件:kube-proxy.kubeconfig

    cat > /k8s/kubernetes/cfg/kube-proxy.kubeconfig <<'EOF'
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority: /k8s/kubernetes/ssl/ca.pem
        server: https://192.168.137.14:6443
      name: kubernetes
    contexts:
    - context:
        cluster: kubernetes
        user: kube-proxy
      name: default
    current-context: default
    kind: Config
    preferences: {}
    users:
    - name: kube-proxy
      user:
        client-certificate: /k8s/kubernetes/ssl/kube-proxy.pem
        client-key: /k8s/kubernetes/ssl/kube-proxy-key.pem
    EOF
    

    ② 创建 kube-proxy 配置文件:kube-proxy-config.yml

    cat > /k8s/kubernetes/cfg/kube-proxy-config.yml <<'EOF'
    kind: KubeProxyConfiguration
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    address: 0.0.0.0
    metrisBindAddress: 0.0.0.0:10249
    clientConnection:
      kubeconfig: /k8s/kubernetes/cfg/kube-proxy.kubeconfig
    hostnameOverride: k8s-node-1
    clusterCIDR: 10.0.0.0/24
    mode: ipvs
    ipvs:
      scheduler: "rr"
    iptables:
      masqueradeAll: true
    EOF
    

    说明:

    • metrisBindAddress:采集指标暴露的地址端口,便于监控系统,采集数据
    • clusterCIDR:集群 Service 网段

    ③ 创建 kube-proxy 配置文件:kube-proxy.conf

    cat > /k8s/kubernetes/cfg/kube-proxy.conf <<'EOF'
    KUBE_PROXY_OPTS="--config=/k8s/kubernetes/cfg/kube-proxy-config.yml \
      --v=2 \
      --logtostderr=false \
      --log-dir=/k8s/kubernetes/logs"
    EOF
    

    ④ 创建 kube-proxy 服务:kube-proxy.service

    cat > /usr/lib/systemd/system/kube-proxy.service <<'EOF'
    [Unit]
    Description=Kubernetes Proxy
    After=network.target
    
    [Service]
    EnvironmentFile=/k8s/kubernetes/cfg/kube-proxy.conf
    ExecStart=/k8s/kubernetes/bin/kube-proxy $KUBE_PROXY_OPTS
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    ⑤ 启动 kube-proxy
    启动服务:

    systemctl daemon-reload
    systemctl start kube-proxy
    

    开机启动:

    systemctl enable kube-proxy
    

    查看启动日志:

    tail -f /k8s/kubernetes/logs/kube-proxy.INFO
    

    5、部署其它Node节点
    部署其它 Node 节点基于与上述流程一致,只需将配置文件中 k8s-node-1 改为 k8s-node-2 即可。

    [root@k8s-master-1 ssl]# kubectl get node -o wide
    NAME         STATUS     ROLES    AGE     VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION           CONTAINER-RUNTIME
    k8s-node-1   NotReady   <none>   19m     v1.16.2   192.168.137.16   <none>        CentOS Linux 7 (Core)   3.10.0-1127.el7.x86_64   docker://24.0.6
    k8s-node-2   NotReady   <none>   2m57s   v1.16.2   192.168.137.17   <none>        CentOS Linux 7 (Core)   3.10.0-1127.el7.x86_64   docker://24.0.6
    

    6、部署K8S容器集群网络(Flannel)

    ① K8S 集群网络

    Kubernetes 项目并没有使用 Docker 的网络模型,kubernetes 是通过一个 CNI 接口维护一个单独的网桥来代替 docker0,这个网桥默认叫 cni0

    CNI(Container Network Interface)是CNCF旗下的一个项目,由一组用于配置 Linux 容器的网络接口的规范和库组成,同时还包含了一些插件。CNI仅关心容器创建时的网络分配,和当容器被删除时释放网络资源。

    Flannel 是 CNI 的一个插件,可以看做是 CNI 接口的一种实现。Flannel 是针对 Kubernetes 设计的一个网络规划服务,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。

    Flannel 网络架构请参考:flannel 网络架构

    ② 创建 CNI 工作目录

    通过给 kubelet 传递 --network-plugin=cni 命令行选项来启用 CNI 插件。 kubelet 从 --cni-conf-dir (默认是 /etc/cni/net.d)读取配置文件并使用该文件中的 CNI 配置来设置每个 pod 的网络。CNI 配置文件必须与 CNI 规约匹配,并且配置引用的任何所需的 CNI 插件都必须存在于 --cni-bin-dir(默认是 /opt/cni/bin)指定的目录。

    由于前面部署 kubelet 服务时,指定了 --cni-conf-dir=/etc/cni/net.d--cni-bin-dir=/opt/cni/bin,因此首先在node节点上创建这两个目录:

    mkdir -p /opt/cni/bin /etc/cni/net.d
    

    ③ 装 CNI 插件

    可以从 github 上下载 CNI 插件:下载 CNI 插件

    mkdir -p /data/soft && cd /data/soft/
    wget https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz
    tar zxf cni-plugins-linux-amd64-v1.1.1.tgz -C /opt/cni/bin/
    cd /opt/cni/bin/
    
    [root@k8s-node-1 bin]# ls
    bandwidth  bridge  dhcp  firewall  host-device  host-local  ipvlan  loopback  macvlan  portmap  ptp  sbr  static  tuning  vlan  vrf
    

    ④ 部署 Flannel

    下载 flannel 配置文件:

    cat >> /etc/hosts << EOF
    185.199.110.133 raw.githubusercontent.com
    EOF
    
    cd /k8s/kubernetes/cfg
    
    wget https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml
    

    注意如下配置:Network 的地址需与** kube-controller-manager.conf** 中的 --cluster-cidr=10.244.0.0/16 保持一致。

    在 k8s-master-1 节点上部署 Flannel:

    [root@k8s-master-1 cfg]# kubectl apply -f kube-flannel.yml
    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-amd64 created
    daemonset.apps/kube-flannel-ds-arm64 created
    daemonset.apps/kube-flannel-ds-arm created
    daemonset.apps/kube-flannel-ds-ppc64le created
    daemonset.apps/kube-flannel-ds-s390x created
    

    ⑤ 检查部署状态

    Flannel 会在 Node 上起一个 Flannel 的 Pod,可以查看 pod 的状态看 flannel 是否启动成功:

    [root@k8s-master-1 cfg]# kubectl get pods -n kube-system -o wide
    NAME                          READY   STATUS     RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES
    kube-flannel-ds-amd64-k77nl   0/1     Init:0/1   0          3m41s   192.168.137.17   k8s-node-2   <none>           <none>
    kube-flannel-ds-amd64-s7b7b   0/1     Init:0/1   0          3m41s   192.168.137.16   k8s-node-1   <none>           <none>
    

    观察 k8s-node-1/2 上面的 kubelet 的输出,存在报错,kubernetes/pause:latest镜像无法拉取

    [root@k8s-node-1 ~]# journalctl -f -u kubelet
    -- Logs begin at 一 2023-09-18 14:01:17 CST. --
    9月 18 22:56:03 k8s-node-1 kubelet[29325]: E0918 22:56:03.561630   29325 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
    9月 18 22:56:08 k8s-node-1 kubelet[29325]: E0918 22:56:08.570365   29325 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
    9月 18 22:56:13 k8s-node-1 kubelet[29325]: E0918 22:56:13.583713   29325 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
    9月 18 22:56:14 k8s-node-1 kubelet[29325]: E0918 22:56:14.011477   29325 aws_credentials.go:77] while getting AWS credentials NoCredentialProviders: no valid providers in chain. Deprecated.
    9月 18 22:56:14 k8s-node-1 kubelet[29325]: For verbose messaging see aws.Config.CredentialsChainVerboseErrors
    9月 18 22:56:18 k8s-node-1 kubelet[29325]: E0918 22:56:18.312985   29325 remote_runtime.go:105] RunPodSandbox from runtime service failed: rpc error: code = Unknown desc = failed pulling image "kubernetes/pause:latest": Error response from daemon: manifest for kubernetes/pause:latest not found: manifest unknown: manifest unknown
    9月 18 22:56:18 k8s-node-1 kubelet[29325]: E0918 22:56:18.313023   29325 kuberuntime_sandbox.go:68] CreatePodSandbox for pod "kube-flannel-ds-amd64-s7b7b_kube-system(71fc2598-b9e6-401f-a4ba-795184198586)" failed: rpc error: code = Unknown desc = failed pulling image "kubernetes/pause:latest": Error response from daemon: manifest for kubernetes/pause:latest not found: manifest unknown: manifest unknown
    9月 18 22:56:18 k8s-node-1 kubelet[29325]: E0918 22:56:18.313039   29325 kuberuntime_manager.go:710] createPodSandbox for pod "kube-flannel-ds-amd64-s7b7b_kube-system(71fc2598-b9e6-401f-a4ba-795184198586)" failed: rpc error: code = Unknown desc = failed pulling image "kubernetes/pause:latest": Error response from daemon: manifest for kubernetes/pause:latest not found: manifest unknown: manifest unknown
    9月 18 22:56:18 k8s-node-1 kubelet[29325]: E0918 22:56:18.313084   29325 pod_workers.go:191] Error syncing pod 71fc2598-b9e6-401f-a4ba-795184198586 ("kube-flannel-ds-amd64-s7b7b_kube-system(71fc2598-b9e6-401f-a4ba-795184198586)"), skipping: failed to "CreatePodSandbox" for "kube-flannel-ds-amd64-s7b7b_kube-system(71fc2598-b9e6-401f-a4ba-795184198586)" with CreatePodSandboxError: "CreatePodSandbox for pod \"kube-flannel-ds-amd64-s7b7b_kube-system(71fc2598-b9e6-401f-a4ba-795184198586)\" failed: rpc error: code = Unknown desc = failed pulling image \"kubernetes/pause:latest\": Error response from daemon: manifest for kubernetes/pause:latest not found: manifest unknown: manifest unknown"
    9月 18 22:56:18 k8s-node-1 kubelet[29325]: E0918 22:56:18.589370   29325 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
    9月 18 22:56:23 k8s-node-1 kubelet[29325]: E0918 22:56:23.594946   29325 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
    

    k8s-node-1/2 上不知道什么原因,无法拉取

    [root@k8s-node-2 ~]# docker search kubernetes/pause
    NAME               DESCRIPTION                               STARS     OFFICIAL   AUTOMATED
    kubernetes/pause   restore from backup of kubernetes/pause   13                   
    [root@k8s-node-2 ~]# docker pull kubernetes/pause
    Using default tag: latest
    Error response from daemon: manifest for kubernetes/pause:latest not found: manifest unknown: manifest unknown
    

    为了解决错误,手动拉取其他镜像,然后重新打tag来处理,这样就没问题了

    [root@k8s-node-1 ~]# docker pull mirrorgooglecontainers/pause:3.1
    3.1: Pulling from mirrorgooglecontainers/pause
    67ddbfb20a22: Pull complete 
    Digest: sha256:59eec8837a4d942cc19a52b8c09ea75121acc38114a2c68b98983ce9356b8610
    Status: Downloaded newer image for mirrorgooglecontainers/pause:3.1
    docker.io/mirrorgooglecontainers/pause:3.1
    [root@k8s-node-1 ~]# docker images
    REPOSITORY                     TAG       IMAGE ID       CREATED       SIZE
    mirrorgooglecontainers/pause   3.1       da86e6ba6ca1   5 years ago   742kB
    [root@k8s-node-1 ~]# docker tag mirrorgooglecontainers/pause:3.1 kubernetes/pause:latest
    [root@k8s-node-1 ~]# docker images
    REPOSITORY                     TAG       IMAGE ID       CREATED       SIZE
    kubernetes/pause               latest    da86e6ba6ca1   5 years ago   742kB
    mirrorgooglecontainers/pause   3.1       da86e6ba6ca1   5 years ago   742kB
    

    同理,k8s-node-2 一样处理,查看 pod 的状态看 flannel 是否启动成功

    [root@k8s-master-1 cfg]# kubectl get pods -n kube-system -o wide
    NAME                          READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
    kube-flannel-ds-amd64-k77nl   1/1     Running   0          34m   192.168.137.17   k8s-node-2   <none>           <none>
    kube-flannel-ds-amd64-s7b7b   1/1     Running   0          34m   192.168.137.16   k8s-node-1   <none>           <none>
    

    Flannel 部署成功后,就可以看 Node 是否就绪:

    [root@k8s-master-1 cfg]# kubectl get nodes -o wide
    NAME         STATUS   ROLES    AGE     VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION           CONTAINER-RUNTIME
    k8s-node-1   Ready    <none>   5h55m   v1.16.2   192.168.137.16   <none>        CentOS Linux 7 (Core)   3.10.0-1127.el7.x86_64   docker://24.0.6
    k8s-node-2   Ready    <none>   5h39m   v1.16.2   192.168.137.17   <none>        CentOS Linux 7 (Core)   3.10.0-1127.el7.x86_64   docker://24.0.6
    

    在 Node 上查看网络配置,可以看到多了一个 flannel.1 的虚拟网卡,这块网卡用于接收 Pod 的流量并转发出去。


    ⑥ 测试创建 Pod

    例如创建一个 Nginx 服务:

    [root@k8s-master-1 cfg]# kubectl create deployment web --image=nginx
    deployment.apps/web created
    

    查看 Pod 状态,容器被部署到k8s-node-1

    [root@k8s-master-1 cfg]# kubectl get pods -o wide
    NAME                  READY   STATUS              RESTARTS   AGE   IP       NODE         NOMINATED NODE   READINESS GATES
    web-d86c95cc9-wcjp6   0/1     ContainerCreating   0          32s   <none>   k8s-node-1   <none>           <none>
    

    在对应的k8s-node-1节点上可以看到部署的容器:

    [root@k8s-node-1 soft]# docker ps -a
    CONTAINER ID   IMAGE                     COMMAND                   CREATED              STATUS                      PORTS     NAMES
    7068e2c4b1bd   nginx                     "/docker-entrypoint.…"   About a minute ago   Up About a minute                     k8s_nginx_web-d86c95cc9-wcjp6_default_08f51dcd-0d1d-4a52-8cc1-9673a8ab2581_0
    57c6c3eebb5f   kubernetes/pause:latest   "/pause"                  2 minutes ago        Up 2 minutes                          k8s_POD_web-d86c95cc9-wcjp6_default_08f51dcd-0d1d-4a52-8cc1-9673a8ab2581_0
    f7b02f620190   ff281650a721              "/opt/bin/flanneld -…"   19 minutes ago       Up 19 minutes                         k8s_kube-flannel_kube-flannel-ds-amd64-s7b7b_kube-system_71fc2598-b9e6-401f-a4ba-795184198586_0
    62f71925e927   quay.io/coreos/flannel    "cp -f /etc/kube-fla…"   19 minutes ago       Exited (0) 19 minutes ago             k8s_install-cni_kube-flannel-ds-amd64-s7b7b_kube-system_71fc2598-b9e6-401f-a4ba-795184198586_0
    2bc5e3a5f596   kubernetes/pause:latest   "/pause"                  20 minutes ago       Up 20 minutes                         k8s_POD_kube-flannel-ds-amd64-s7b7b_kube-system_71fc2598-b9e6-401f-a4ba-795184198586_0
    

    容器创建成功后,再在 Node 上查看网络配置,又多了一块 cni0 的虚拟网卡,cni0 用于 pod 本地通信使用



    暴露端口并访问 Nginx:

    [root@k8s-master-1 cfg]# kubectl expose deployment web --port=80 --type=NodePort
    service/web exposed
    [root@k8s-master-1 cfg]# kubectl get pods,svc
    NAME                      READY   STATUS    RESTARTS   AGE
    pod/web-d86c95cc9-wcjp6   1/1     Running   0          9m35s
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    service/kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP        8h
    service/web          NodePort    10.0.0.141   <none>        80:31896/TCP   15s
    [root@k8s-master-1 cfg]# curl k8s-node-1:31896
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    html { color-scheme: light dark; }
    body { width: 35em; margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif; }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    

    7、部署内部 DNS 服务

    在Kubernetes集群推荐使用Service Name作为服务的访问地址,因此需要一个Kubernetes集群范围的DNS服务实现从Service Name到Cluster IP的解析,这就是Kubernetes基于DNS的服务发现功能。

    ① 部署 CoreDNS

    [root@k8s-master-1 cfg]# cat coredns.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: coredns
      namespace: kube-system
      labels:
          kubernetes.io/cluster-service: "true"
          addonmanager.kubernetes.io/mode: Reconcile
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      labels:
        kubernetes.io/bootstrapping: rbac-defaults
        addonmanager.kubernetes.io/mode: Reconcile
      name: system:coredns
    rules:
    - apiGroups:
      - ""
      resources:
      - endpoints
      - services
      - pods
      - namespaces
      verbs:
      - list
      - watch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      annotations:
        rbac.authorization.kubernetes.io/autoupdate: "true"
      labels:
        kubernetes.io/bootstrapping: rbac-defaults
        addonmanager.kubernetes.io/mode: EnsureExists
      name: system:coredns
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: system:coredns
    subjects:
    - kind: ServiceAccount
      name: coredns
      namespace: kube-system
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: coredns
      namespace: kube-system
      labels:
          addonmanager.kubernetes.io/mode: EnsureExists
    data:
      Corefile: |
        .:53 {
            errors
            health
            kubernetes cluster.local in-addr.arpa ip6.arpa {
                pods insecure
                upstream
                fallthrough in-addr.arpa ip6.arpa
            }
            prometheus :9153
            proxy . /etc/resolv.conf
            cache 30
            loop
            reload
            loadbalance
        }
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: coredns
      namespace: kube-system
      labels:
        k8s-app: kube-dns
        kubernetes.io/cluster-service: "true"
        addonmanager.kubernetes.io/mode: Reconcile
        kubernetes.io/name: "CoreDNS"
    spec:
      # replicas: not specified here:
      # 1. In order to make Addon Manager do not reconcile this replicas parameter.
      # 2. Default is 1.
      # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 1
      selector:
        matchLabels:
          k8s-app: kube-dns
      template:
        metadata:
          labels:
            k8s-app: kube-dns
          annotations:
            seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
        spec:
          serviceAccountName: coredns
          tolerations:
            - key: node-role.kubernetes.io/master
              effect: NoSchedule
            - key: "CriticalAddonsOnly"
              operator: "Exists"
          containers:
          - name: coredns
            image: coredns/coredns:1.2.6
            imagePullPolicy: IfNotPresent
            resources:
              limits:
                memory: 170Mi
              requests:
                cpu: 100m
                memory: 70Mi
            args: [ "-conf", "/etc/coredns/Corefile" ]
            volumeMounts:
            - name: config-volume
              mountPath: /etc/coredns
              readOnly: true
            ports:
            - containerPort: 53
              name: dns
              protocol: UDP
            - containerPort: 53
              name: dns-tcp
              protocol: TCP
            - containerPort: 9153
              name: metrics
              protocol: TCP
            livenessProbe:
              httpGet:
                path: /health
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 60
              timeoutSeconds: 5
              successThreshold: 1
              failureThreshold: 5
            securityContext:
              allowPrivilegeEscalation: false
              capabilities:
                add:
                - NET_BIND_SERVICE
                drop:
                - all
              readOnlyRootFilesystem: true
          dnsPolicy: Default
          volumes:
            - name: config-volume
              configMap:
                name: coredns
                items:
                - key: Corefile
                  path: Corefile
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: kube-dns
      namespace: kube-system
      annotations:
        prometheus.io/port: "9153"
        prometheus.io/scrape: "true"
      labels:
        k8s-app: kube-dns
        kubernetes.io/cluster-service: "true"
        addonmanager.kubernetes.io/mode: Reconcile
        kubernetes.io/name: "CoreDNS"
    spec:
      selector:
        k8s-app: kube-dns
      clusterIP: 10.0.0.2 
      ports:
      - name: dns
        port: 53
        protocol: UDP
      - name: dns-tcp
        port: 53
        protocol: TCP
    

    注意如下 clusterIP 一定要与 kubelet-config.yaml 中的 clusterDNS 保持一致


    部署 CoreDNS:
    [root@k8s-master-1 cfg]# kubectl apply -f coredns.yaml
    serviceaccount/coredns created
    clusterrole.rbac.authorization.k8s.io/system:coredns created
    clusterrolebinding.rbac.authorization.k8s.io/system:coredns created
    configmap/coredns created
    deployment.apps/coredns created
    service/kube-dns created
    

    ② 验证 CoreDNS

    创建 busybox 服务:

    cat > busybox.yaml <<'EOF'
    apiVersion: v1
    kind: Pod
    metadata:
      name: busybox
      namespace: default
    spec:
      dnsPolicy: ClusterFirst
      containers:
      - name: busybox
        image: busybox:1.28.4
        command:
          - sleep
          - "3600"
        imagePullPolicy: IfNotPresent
      restartPolicy: Always
    EOF
    
    kubectl apply -f busybox.yaml
    

    验证是否安装成功:

    kubectl exec -ti busybox sh
    

    提示错误:

    [root@k8s-master-1 cfg]# kubectl exec -ti pod/busybox sh
    error: unable to upgrade connection: Forbidden (user=kubernetes, verb=create, resource=nodes, subresource=proxy)
    

    权限问题,参考文章 https://www.kancloud.cn/idzqj/customer/1873079

    [root@k8s-master-1 cfg]# kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes
    clusterrolebinding.rbac.authorization.k8s.io/kube-apiserver:kubelet-apis created
    [root@k8s-master-1 cfg]# kubectl exec -ti pod/busybox sh
    / # nslookup web
    Server:    10.0.0.2
    Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
    
    Name:      web
    Address 1: 10.0.0.141 web.default.svc.cluster.local
    / # exit
    

    八、集群搭建 —— 部署 Dashboard

    K8S 提供了一个 Web 版 Dashboard,用户可以用 dashboard 部署容器化的应用、监控应用的状态,能够创建和修改各种 K8S 资源,比如 Deployment、Job、DaemonSet 等。用户可以 Scale Up/Down Deployment、执行 Rolling Update、重启某个 Pod 或者通过向导部署新的应用。Dashboard 能显示集群中各种资源的状态以及日志信息。Kubernetes Dashboard 提供了 kubectl 的绝大部分功能。

    1、部署 K8S Dashboard

    通过此地址下载 dashboard yaml文件:https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta5/aio/deploy/recommended.yaml
    因为本次kubernetes版本对应的是1.16.2,所以dashboard需要是这个版本对应匹配的版本【v2.0.0-beta5】,一定要对的上,否则会有其他奇奇怪怪的错误

    下载下来之后,需更新如下内容:通过 Node 暴露端口访问 dashboard


    namespace: kubernetes-dashboard 全部替换为 namespace: kube-system
    部署 dashboard:
    [root@k8s-master-1 cfg]# kubectl apply -f kubernetes-dashboard.yaml
    namespace/kubernetes-dashboard unchanged
    serviceaccount/kubernetes-dashboard created
    service/kubernetes-dashboard unchanged
    secret/kubernetes-dashboard-certs created
    secret/kubernetes-dashboard-csrf created
    secret/kubernetes-dashboard-key-holder created
    configmap/kubernetes-dashboard-settings created
    role.rbac.authorization.k8s.io/kubernetes-dashboard created
    clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
    rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
    clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard configured
    deployment.apps/kubernetes-dashboard created
    service/dashboard-metrics-scraper created
    deployment.apps/dashboard-metrics-scraper created
    

    查看是否部署成功:

    [root@k8s-master-1 cfg]# kubectl get pods,svc -n kube-system
    NAME                                             READY   STATUS    RESTARTS   AGE
    pod/coredns-84d8b55f97-cdjwv                     1/1     Running   0          70m
    pod/dashboard-metrics-scraper-76585494d8-lhlhl   1/1     Running   0          7m23s
    pod/kube-flannel-ds-amd64-k77nl                  1/1     Running   0          6d
    pod/kube-flannel-ds-amd64-s7b7b                  1/1     Running   0          6d
    pod/kubernetes-dashboard-5c68c48b47-dfgth        1/1     Running   0          7m23s
    
    NAME                                TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
    service/dashboard-metrics-scraper   ClusterIP   10.0.0.3     <none>        8000/TCP        7m23s
    service/kube-dns                    ClusterIP   10.0.0.2     <none>        53/UDP,53/TCP   70m
    service/kubernetes-dashboard        NodePort    10.0.0.134   <none>        443:30005/TCP   17m
    

    通过 https 访问 dashboard(ip 地址为 node1 或者node2):
    如果提示



    解决办法:在chrome该页面上,在当前页面(也就是上图页面)注意是在当前页面打开的时候点网页任意地方,不是输入框,直接输入thisisunsafe回车,直接就打开页面了


    2、登录授权

    Dashboard 支持 Kubeconfig 和 Token 两种认证方式,为了简化配置,我们通过配置文件为 Dashboard 默认用户赋予 admin 权限。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: admin-user
      namespace: kube-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: admin-user
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: admin-user
      namespace: kube-system
    EOF
    

    授权:

    [root@k8s-master-1 cfg]# kubectl apply -f kubernetes-adminuser.yaml
    serviceaccount/admin-user created
    clusterrolebinding.rbac.authorization.k8s.io/admin-user created
    

    获取登录的 token:

    [root@k8s-master-1 cfg]# kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk ' {print $1}')
    Name:         admin-user-token-hrdpx
    Namespace:    kube-system
    Labels:       <none>
    Annotations:  kubernetes.io/service-account.name: admin-user
                  kubernetes.io/service-account.uid: 5d0b81f2-5b15-4ceb-97e1-f0b35d05b9ce
    
    Type:  kubernetes.io/service-account-token
    
    Data
    ====
    ca.crt:     1383 bytes
    namespace:  11 bytes
    token:      eyJhbGciOiJSUzI1NiIsImtpZCI6InBXa2VKS0Y4TGpFUFFZN2M3c1M1djdNcDhEU09YZnZ4c1dYOENLRWd4ZG8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWhyZHB4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI1ZDBiODFmMi01YjE1LTRjZWItOTdlMS1mMGIzNWQwNWI5Y2UiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.BpsqqIRD6jUwGm9Luya_3Y38ApE__VqmOSQe9tBWMvJ6Uh5uJVyZrWT52mPpTudNJoGSAYqtVPuZIpBZzabyAGeC1BIt0unBHj6B0hEI2Yc6WetfPeHgPhmHQ6K_2W9VQKTW497ZZXuu1A5T-XI7ompWPWF0gC1ZQgZkeVoFaZvRLjrX02e0lFyP_EInL_Wss0-5gh2qDzY1vbocCUaR87Hq8dEpkTBhR9paRwqJaTOf5vtwpcS6I0dk2eivWVmVcDQ8a3s08xdQD1Fd4oRxlqKrMcK9BEFW6WTUjEqgrMCByn3T0fVr9J9rgUfH9WYDXqTUdJevDNeA_0n-7AXzog
    

    通过token登录进 dashboard,就可以查看集群的信息:


    九、集群搭建 —— 多 Master 部署

    1、部署Master2组件

    ① 将 k8s-master-1 上相关文件拷贝到 k8s-master-2 上

    创建k8s工作目录:

    [root@k8s-master-2 ~]# mkdir -p /k8s/kubernetes
    [root@k8s-master-2 ~]# mkdir -p /k8s/etcd
    [root@k8s-master-2 ~]# mkdir -p /data/soft
    

    拷贝 k8s 配置文件、执行文件、证书:
    k8s-master-1 上执行

    scp -r /k8s/kubernetes/{cfg,ssl,bin} root@k8s-master-2:/k8s/kubernetes
    scp -r /data/soft/ root@k8s-master-2:/data/
    

    k8s-master-2 上执行

    cp -p /data/soft/kubernetes/server/bin/kubectl /usr/local/bin/
    

    拷贝 etcd 证书:

    [root@k8s-master-1 cfg]# scp -r /k8s/etcd/ssl root@k8s-master-2:/k8s/etcd
    

    拷贝 k8s 服务的service文件:

    [root@k8s-master-1 cfg]# scp /usr/lib/systemd/system/kube-* root@k8s-master-2:/usr/lib/systemd/system
    

    ② 修改 k8s-master-2 上的配置文件

    修改 kube-apiserver.conf,修改IP为本机IP


    ③ 启动 k8s-master-2 组件

    重新加载配置:

    systemctl daemon-reload
    

    启动 kube-apiserver:

    systemctl start kube-apiserver
    systemctl enable kube-apiserver
    

    启动 kube-controller-manager:

    systemctl start kube-controller-manager
    systemctl enable kube-controller-manager
    

    部署 kube-scheduler:

    systemctl start kube-scheduler
    systemctl enable kube-scheduler
    

    ④ 验证

    [root@k8s-master-2 ~]# kubectl get nodes
    NAME         STATUS   ROLES    AGE    VERSION
    k8s-node-1   Ready    <none>   6d6h   v1.16.2
    k8s-node-2   Ready    <none>   6d6h   v1.16.2
    [root@k8s-master-2 ~]# kubectl get pods
    NAME                  READY   STATUS    RESTARTS   AGE
    busybox               1/1     Running   1          107m
    web-d86c95cc9-wcjp6   1/1     Running   0          6d
    

    2、部署 Nginx 负载均衡
    为了保证 k8s master 的高可用,将使用 k8s-lb-master 和 k8s-lb-backup 这两台机器来部署负载均衡。这里使用 nginx 做负载均衡器,下面分别在 k8s-lb-master 和 k8s-lb-backup 这两台机器上部署 nginx。

    ① gcc等环境安装,后续有些软件安装需要这些基础环境

    # gcc安装:
    yum install gcc-c++
    # PCRE pcre-devel 安装:
    yum install -y pcre pcre-devel
    # zlib 安装:
    yum install -y zlib zlib-devel
    #OpenSSL 安装:
    yum install -y openssl openssl-devel
    

    ② 安装nginx

    rpm -ivh https://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm
    

    ③ apiserver 负载配置

    vim /etc/nginx/nginx.conf
    

    增加如下配置:

    stream {
        log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
        access_log /var/log/nginx/k8s-access.log main;
    
        upstream k8s-apiserver {
            server 192.168.137.14:6443;
            server 192.168.137.15:6443;
        }
    
        server {
            listen 6443;
            proxy_pass k8s-apiserver;
        }
    }
    

    ④ 启动 nginx

    systemctl start nginx
    systemctl enable nginx
    

    3、部署 KeepAlive
    为了保证 nginx 的高可用,还需要部署 keepalive,keepalive 主要负责 nginx 的健康检查和故障转移。

    ① 分别在 k8s-lb-master 和 k8s-lb-backup 这两台机器上安装 keepalive

    yum install keepalived -y
    

    ② master 启动 keepalived

    修改 k8s-lb-master keepalived 配置文件

    cat > /etc/keepalived/keepalived.conf <<'EOF'
    global_defs {
       script_user root
       enable_script_security
    
       notification_email {
         acassen@firewall.loc
         failover@firewall.loc
         sysadmin@firewall.loc
       }
       notification_email_from Alexandre.Cassen@firewall.loc
       smtp_server 127.0.0.1
       smtp_connect_timeout 30
       router_id NGINX_MASTER
    }
    
    vrrp_script check_nginx {
       script "/etc/keepalived/check_nginx.sh" 
    }
    
    # vrrp实例
    vrrp_instance VI_1 {
        state MASTER 
        interface eth0
        virtual_router_id 51 
        priority 100
        advert_int 1 
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.137.100/24 
        }
        track_script {
            check_nginx
        }
    }
    EOF
    

    配置说明:

    • vrrp_script:用于健康检查nginx状态,如果nginx没有正常工作,就会进行故障漂移,使备节点接管VIP,这里通过 shell 脚本来检查nginx状态
    • state:keepalived 角色,主节点为 MASTER,备节点为 BACKUP
    • interface:接口,配置本地网卡名,keepalived 会将虚拟IP绑定到这个网卡上
    • virtual_router_id:#VRRP 路由ID实例,每个实例是唯一的
    • priority:优先级,备服务器设置90
    • advert_int:指定VRRP心跳包通告间隔时间,默认1秒
    • virtual_ipaddress:VIP,要与当前机器在同一网段,keepalived 会在网卡上附加这个IP,之后通过这个IP来访问Nginx,当nginx不可用时,会将此虚拟IP漂移到备节点上。

    增加 check_nginx.sh 脚本,通过此脚本判断 nginx 是否正常:

    cat > /etc/keepalived/check_nginx.sh <<'EOF'
    #!/bin/bash
    count=$(ps -ef | grep nginx | egrep -cv "grep|$$")
    if [ "$count" -eq 0 ];then
        exit 1;
    else 
        exit 0;
    fi
    EOF
    

    增加可执行权限:

    chmod +x /etc/keepalived/check_nginx.sh
    

    启动 keepalived:

    systemctl start keepalived
    systemctl enable keepalived
    

    ③ backup 启动 keepalived

    修改 k8s-lb-backup keepalived 配置文件

    cat > /etc/keepalived/keepalived.conf <<'EOF'
    global_defs {
       script_user root
       enable_script_security
    
       notification_email {
         acassen@firewall.loc
         failover@firewall.loc
         sysadmin@firewall.loc
       }
       notification_email_from Alexandre.Cassen@firewall.loc
       smtp_server 127.0.0.1
       smtp_connect_timeout 30
       router_id NGINX_BACKUP
    }
    
    vrrp_script check_nginx {
       script "/etc/keepalived/check_nginx.sh"
    }
    
    # vrrp实例
    vrrp_instance VI_1 {
        state BACKUP
        interface eth0
        virtual_router_id 51
        priority 90
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.137.100/24
        }
        track_script {
            check_nginx
        }
    }
    EOF
    

    增加 check_nginx.sh 脚本:

    cat > /etc/keepalived/check_nginx.sh <<'EOF'
    #!/bin/bash
    count=$(ps -ef | grep nginx | egrep -cv "grep|$$")
    if [ "$count" -eq 0 ];then
        exit 1;
    else 
        exit 0;
    fi
    EOF
    

    增加可执行权限:

    chmod +x /etc/keepalived/check_nginx.sh
    

    启动 keepalived:

    systemctl start keepalived
    systemctl enable keepalived
    

    注意:本地网卡名可以先通过 ip a查看下,按自己实际的来,我的虚拟机是eth0

    ④ 验证负载均衡

    keepalived 已经将VIP附加到MASTER所在的网卡上

    [root@k8s-lb-master ~]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 00:15:5d:0a:0e:0d brd ff:ff:ff:ff:ff:ff
        inet 192.168.137.18/24 brd 192.168.137.255 scope global noprefixroute eth0
           valid_lft forever preferred_lft forever
        inet 192.168.137.100/24 scope global secondary eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::fdca:50bb:5250:8fce/64 scope link noprefixroute 
           valid_lft forever preferred_lft forever
    

    BACKUP节点上并没有

    [root@k8s-lb-backup nginx]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 00:15:5d:0a:0e:0e brd ff:ff:ff:ff:ff:ff
        inet 192.168.137.19/24 brd 192.168.137.255 scope global noprefixroute eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::195d:5816:625e:75f/64 scope link noprefixroute 
           valid_lft forever preferred_lft forever
    

    关闭 k8s-lb-master 上的nginx,可看到VIP已经不在了

    [root@k8s-lb-master ~]# systemctl stop nginx
    [root@k8s-lb-master ~]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 00:15:5d:0a:0e:0d brd ff:ff:ff:ff:ff:ff
        inet 192.168.137.18/24 brd 192.168.137.255 scope global noprefixroute eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::fdca:50bb:5250:8fce/64 scope link noprefixroute 
           valid_lft forever preferred_lft forever
    

    可以看到已经漂移到备节点上了,如果再重启 MASTER 上的 Ngnix,VIP又会漂移到主节点上。

    [root@k8s-lb-backup nginx]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 00:15:5d:0a:0e:0e brd ff:ff:ff:ff:ff:ff
        inet 192.168.137.19/24 brd 192.168.137.255 scope global noprefixroute eth0
           valid_lft forever preferred_lft forever
        inet 192.168.137.100/24 scope global secondary eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::195d:5816:625e:75f/64 scope link noprefixroute 
           valid_lft forever preferred_lft forever
    

    访问虚拟IP还是可以访问的

    [root@k8s-master-1 ~]# curl 192.168.137.100
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    

    4、Node节点连接VIP

    ① 修改 node 节点的配置文件中连接 k8s-master 的IP为VIP
    node1

    [root@k8s-node-1 cfg]# pwd
    /k8s/kubernetes/cfg
    [root@k8s-node-1 cfg]# grep 192 *
    bootstrap.kubeconfig:    server: https://192.168.137.14:6443
    kubelet.kubeconfig:    server: https://192.168.137.14:6443
    kube-proxy.kubeconfig:    server: https://192.168.137.14:6443
    [root@k8s-node-1 cfg]# sed -i 's#192.168.137.14#192.168.137.100#' *
    [root@k8s-node-1 cfg]# grep 192 *
    bootstrap.kubeconfig:    server: https://192.168.137.100:6443
    kubelet.kubeconfig:    server: https://192.168.137.100:6443
    kube-proxy.kubeconfig:    server: https://192.168.137.100:6443
    

    ② 重启 kubelet 和 kube-proxy

    systemctl restart kubelet
    systemctl restart kube-proxy
    

    node2同样操作

    ③ 在 node 节点上访问VIP调用 apiserver 验证

    Authorization 的token 是前面生成 token.csv 中的令牌。

    [root@k8s-node-1 cfg]# ssh root@k8s-master-1 'cat /k8s/kubernetes/cfg/token.csv'
    root@k8s-master-1's password: 
    b9187da74c444ee060a1c6053eab97c7,kubelet-bootstrap,10001,"system:node-bootstrapper"
    [root@k8s-node-1 cfg]# curl -k --header "Authorization: Bearer b9187da74c444ee060a1c6053eab97c7" https://192.168.137.100:6443/version
    {
      "major": "1",
      "minor": "16",
      "gitVersion": "v1.16.2",
      "gitCommit": "c97fe5036ef3df2967d086711e6c0c405941e14b",
      "gitTreeState": "clean",
      "buildDate": "2019-10-15T19:09:08Z",
      "goVersion": "go1.12.10",
      "compiler": "gc",
      "platform": "linux/amd64"
    

    相关文章

      网友评论

          本文标题:Kubernets集群部署(二进制包编译方式)

          本文链接:https://www.haomeiwen.com/subject/eusivdtx.html