Rocky Linux 9 二进制方式部署 K8s 集群

温馨提醒

环境

系统IP角色
Rocky Linux 9.310.203.0.10VIP
Rocky Linux 9.310.203.0.11master-01
Rocky Linux 9.310.203.0.12master-02
Rocky Linux 9.310.203.0.13master-03
Rocky Linux 9.310.203.0.14node-01
Rocky Linux 9.310.203.0.15node-02

系统初始化

  • 关闭防火墙

    1
    
    systemctl disable --now firewalld
  • 关闭 selinux

    1
    2
    
    setenforce 0
    sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
  • 关闭 swap

  • 配置主机名

    1
    2
    3
    4
    5
    
    hostnamectl set-hostname master-01
    hostnamectl set-hostname master-02
    hostnamectl set-hostname master-03
    hostnamectl set-hostname node-01
    hostnamectl set-hostname node-02
  • 添加所有节点的 hosts 解析

    1
    2
    3
    4
    5
    6
    7
    
    cat >> /etc/hosts << EOF
    10.203.0.11     master-01
    10.203.0.12     master-02
    10.203.0.13     master-03
    10.203.0.14		node-01
    10.203.0.15		node-02
    EOF
  • 安装基本包

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    # 对于 Ubuntu
    apt update && apt upgrade -y && apt install -y lrzsz wget psmisc vim net-tools nfs-kernel-server telnet lvm2 git tar curl dos2unix socat
    
    # 对于 CentOS 7
    yum update -y && yum -y install lrzsz wget psmisc vim net-tools nfs-utils telnet yum-utils device-mapper-persistent-data lvm2 git tar curl dos2unix socat
    
    # 对于 CentOS 8
    dnf update -y && dnf -y install lrzsz wget psmisc vim net-tools nfs-utils telnet yum-utils device-mapper-persistent-data lvm2 git network-scripts tar curl dos2unix socat
    
    # 对于 CentOS 9
    dnf update -y && dnf -y install lrzsz wget psmisc vim net-tools nfs-utils telnet yum-utils device-mapper-persistent-data lvm2 git tar curl dos2unix socat
  • 配置内核

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    cat >  /etc/sysctl.d/k8s.conf << EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
    net.ipv4.ip_nonlocal_bind = 1
    net.ipv4.neigh.default.gc_thresh1 = 80000
    net.ipv4.neigh.default.gc_thresh2 = 90000
    net.ipv4.neigh.default.gc_thresh3 = 100000
    EOF
    
    modprobe br_netfilter
    
    sysctl --system
  • 配置 ulimit

    1
    2
    3
    4
    5
    6
    7
    8
    
    cat >> /etc/security/limits.conf << EOF
    * soft nproc 655360
    * hard nproc 655360
    * soft nofile 655360
    * hard nofile 655360
    * seft memlock unlimited
    * hard memlock unlimited
    EOF
  • 安装 ipvsadm

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    yum install ipvsadm ipset sysstat conntrack libseccomp -y
    
    cat > /etc/modules-load.d/ipvs.conf <<EOF 
    ip_vs
    ip_vs_rr
    ip_vs_wrr
    ip_vs_sh
    nf_conntrack
    ip_tables
    ip_set
    xt_set
    ipt_set
    ipt_rpfilter
    ipt_REJECT
    ipip
    EOF
    
    systemctl restart systemd-modules-load.service
    
    lsmod | grep -e ip_vs -e nf_conntrack
  • 配置免密(master-01 到所有节点的)

    1
    2
    3
    4
    5
    6
    
    ssh-keygen -t rsa
    
    ssh-copy-id master-02
    ssh-copy-id master-03
    ssh-copy-id node-01
    ssh-copy-id node-02
  • 配置时钟同步

安装 cfssl 工具

  • 在 master-01 节点上安装证书生成工具

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    curl -s -L -o /usr/local/bin/cfssl https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64
    
    curl -s -L -o /usr/local/bin/cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64
    
    curl -s -L -o /usr/local/bin/cfssl-certinfo https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl-certinfo_1.6.5_linux_amd64
    
    chmod +x /usr/local/bin/cfssl*
    
    cfssl version

部署 etcd 集群

为 etcd 生成自签证书

  • 创建目录(在 master-01节点上)

    1
    
    mkdir /data/k8s/etcd -p && cd /data/k8s/etcd
  • 创建 ca-config.json 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    # 配置加密和认证签名的一些参数,让CA软件知道颁发什么样的证书
    # 分为两个部分:signing和profiles
    # signing部分包含了默认签名配置和配置文件
    # 默认签名配置default指定了证书的过期时间为876000h,表示证书有效期为100年
    # profiles部分定义了不同的证书配置文件
    # 在这里,只有一个配置文件etcd。它包含了以下usages和过期时间expiry
    # 1. signing:表示该证书可用于签名其它证书
    # 2. key encipherment:表示该证书用于加密和解密传输数据
    # 3. server auth:表示client可以使用该CA对server提供的证书进行验证
    # 4. client auth:表示server可以使用该CA对client提供的证书进行验证
    # 5. 对于配置文件etcd,证书的过期时间也是876000h,表示证书有效期为100年
    cat > ca-config.json << EOF
    {
      "signing": {
        "default": {
          "expiry": "876000h"
        },
        "profiles": {
          "etcd": {
             "usages": [
                "signing",
                "key encipherment",
                "server auth",
                "client auth"
            ],
            "expiry": "876000h"
          }
        }
      }
    }
    EOF
  • 创建 ca-csr.json 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    # 这是一个用于生成证书签名请求(Certificate Signing Request,CSR)的JSON配置文件。JSON配置文件指定了生成证书签名请求所需的数据。
    # - "CN": "etcd" 指定了希望生成的证书的CN字段(Common Name),即证书的主题,通常是该证书标识的实体的名称。
    # - "key": {} 指定了生成证书所使用的密钥的配置信息。"algo": "rsa" 指定了密钥的算法为RSA,"size": 2048 指定了密钥的长度为2048位。
    # - "names": [] 包含了生成证书时所需的实体信息。在这个例子中,只包含了一个实体,其相关信息如下:
    # - C:Country,即国家。在此配置中,设置为 "CN"。
    # - ST:State,即省/州。在此配置中,设置为 "LiaoNing"。
    # - L:Locality,即城市。在此配置中,设置为 "DaLian"。
    # - O:Organization,即组织。在此配置中,设置为 "etcd"。
    # - OU:Organization Unit,即组织单位。在此配置中,设置为 "Etcd Security"。
    # - "ca": {} 指定了生成证书时所需的CA(Certificate Authority)配置信息。
    # - "expiry": "876000h" 指定了证书的有效期,这里是876000小时,即100年
    # 生成证书签名请求时,可以使用这个JSON配置文件作为输入,根据配置文件中的信息生成相应的CSR文件。然后,可以将CSR文件发送给CA进行签名,以获得有效的证书。
    cat > etcd-ca-csr.json << EOF
    {
        "CN": "etcd",
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "ST": "LiaoNing",
                "L": "DaLian",
                "O": "etcd",
                "OU": "Etcd Security"
            }
        ],
        "ca": {
        "expiry": "876000h"
      }
    }
    EOF
  • 创建 etcd-csr.json 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    # hosts字段需要把所有etcd集群节点的IP地址都添加进去
    
    # 这是一个JSON格式的配置文件,用于生成一个证书签名请求(Certificate Signing Request,CSR)。
    # 首先,"CN"字段指定了该证书的通用名称(Common Name),这里设为"etcd"。
    # 其次,"hosts"字段指定该证书的授权范围,此处需要把所有etcd集群节点的IP地址都添加进去
    # 接下来,"key"字段指定了密钥的算法("algo"字段)和长度("size"字段),此处使用的是RSA算法,密钥长度为2048位。
    # 最后,"names"字段是一个数组,其中包含了一个名字对象,用于指定证书中的一些其他信息。这个名字对象包含了以下字段:
    # - "C"字段指定了国家代码(Country),这里设置为"CN"。
    # - "ST"字段指定了省份(State)或地区,这里设置为"LiaoNing"。
    # - "L"字段指定了城市(Locality),这里设置为"DaLian"。
    # - "O"字段指定了组织(Organization),这里设置为"etcd"。
    # - "OU"字段指定了组织单元(Organizational Unit),这里设置为"Etcd Security"。
    # 这些字段将作为证书的一部分,用于标识和验证证书的使用范围和颁发者等信息。
    cat > etcd-csr.json << EOF
    {
        "CN": "etcd",
        "hosts": [
            "10.203.0.11",
            "10.203.0.12",
            "10.203.0.13"
            ],
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "ST": "LiaoNing",
                "L": "DaLian",
                "O": "etcd",
                "OU": "Etcd Security"
            }
        ]
    }
    EOF
  • 生成 CA 证书和私钥

    1
    2
    3
    4
    5
    6
    
    # cfssl是一个用于生成TLS/SSL证书的工具,它支持PKI、JSON格式配置文件以及与许多其他集成工具的配合使用。
    # gencert参数表示生成证书的操作。-initca参数表示初始化一个CA(证书颁发机构)。CA是用于签发其他证书的根证书。etcd-ca-csr.json是一个JSON格式的配置文件,其中包含了CA的详细信息,如私钥、公钥、有效期等。这个文件提供了生成CA证书所需的信息。
    # | 为管道符,表示将上一个命令的输出作为下一个命令的输入。
    # cfssljson是cfssl工具的一个子命令,用于格式化cfssl生成的JSON数据。-bare参数表示直接输出裸证书,即只生成证书文件,不包含其他格式的文件。ca是指定生成的证书文件的路径和文件名前缀。
    # 所以,这条命令的作用是使用cfssl工具根据配置文件etcd-ca-csr.json生成一个CA证书,并将证书文件保存在当前路径下,证书文件名前缀为ca,实际生成的文件名为ca.csr、ca.pem、ca-key.pem。
    cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare ca
  • 为 etcd 生成自签证书

    1
    2
    3
    4
    5
    6
    7
    8
    
    # -ca=ca.pem:指定用于签名etcd证书的CA文件的路径;
    # -ca-key=ca-key.pem:指定用于签名etcd证书的CA私钥文件的路径;
    # -config=ca-config.json:指定CA配置文件的路径,该文件定义了证书的有效期、加密算法等设置;
    # -profile=etcd:指定使用的证书配置文件,该文件定义了证书的用途和扩展属性;
    # etcd-csr.json:指定etcd证书请求的JSON文件的路径,该文件包含了证书请求的详细信息;
    # | cfssljson -bare etcd:通过管道符将cfssl命令的输出传递给cfssljson命令,并使用-bare参数直接输出裸证书,即只生成证书文件,不包含其他格式的文件,最后指定证书文件名前缀为etcd,实际生成的文件名为etcd.csr、etcd.pem、etcd-key.pem;
    # 所以,这条命令的作用是使用指定的CA证书和私钥,根据证书请求的JSON文件和配置文件生成etcd的证书文件。
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd etcd-csr.json | cfssljson -bare etcd

部署 etcd 3.5.12(只需要在 master-01 节点操作)

  • 下载安装包

    1
    
    wget https://github.com/etcd-io/etcd/releases/download/v3.5.13/etcd-v3.5.13-linux-amd64.tar.gz
  • 创建目录

    1
    2
    
    # 创建配置文件存放目录、证书存放目录
    mkdir /opt/etcd/{bin,cfg,ssl} -p
  • 解压

    1
    
    tar -xf etcd*.tar.gz && mv etcd-*/etcd* /opt/etcd/bin/
  • 拷贝生成的自签证书到 ssl 目录下

    1
    
    cp /data/k8s/etcd/ca*pem /data/k8s/etcd/etcd*pem /opt/etcd/ssl/
  • 创建 etcd 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    cat > /opt/etcd/cfg/etcd.conf << EOF
    #[Member]
    # 自定义此etcd节点的名称,集群内唯一
    ETCD_NAME="etcd-1"
    # 定义etcd数据存放目录
    ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
    # 定义本机和成员之间通信的地址
    ETCD_LISTEN_PEER_URLS="https://10.203.0.11:2380" 
    # 定义etcd对外提供服务的地址
    ETCD_LISTEN_CLIENT_URLS="https://10.203.0.11:2379,http://127.0.0.1:2379"
    
    #[Clustering]
    # 定义该节点成员对等URL地址,且会通告集群的其余成员节点
    ETCD_INITIAL_ADVERTISE_PEER_URLS="https://10.203.0.11:2380"
    # 此成员的客户端URL列表,用于通告群集的其余部分
    ETCD_ADVERTISE_CLIENT_URLS="https://10.203.0.11:2379"
    # 集群中所有节点的信息
    ETCD_INITIAL_CLUSTER="etcd-1=https://10.203.0.11:2380,etcd-2=https://10.203.0.12:2380,etcd-3=https://10.203.0.13:2380"
    # 创建集群的token,这个值每个集群保持唯一
    ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
    # 设置new为初始静态或DNS引导期间出现的所有成员。如果将此选项设置为existing,则etcd将尝试加入现有群集
    ETCD_INITIAL_CLUSTER_STATE="new"
    # flannel操作etcd使用的是v2的API,而kubernetes操作etcd使用的v3的API,在ETCD3.5版本中默认关闭v2版本,所以为了兼容flannel,要设置开启v2的API
    ETCD_ENABLE_V2="true"
    EOF
  • 创建 systemd 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    cat > /usr/lib/systemd/system/etcd.service << EOF
    [Unit]
    Description=Etcd Server
    After=network.target
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=notify
    EnvironmentFile=/opt/etcd/cfg/etcd.conf
    ExecStart=/opt/etcd/bin/etcd \\
            --cert-file=/opt/etcd/ssl/etcd.pem \\
            --key-file=/opt/etcd/ssl/etcd-key.pem \\
            --peer-cert-file=/opt/etcd/ssl/etcd.pem \\
            --peer-key-file=/opt/etcd/ssl/etcd-key.pem \\
            --trusted-ca-file=/opt/etcd/ssl/ca.pem \\
            --peer-trusted-ca-file=/opt/etcd/ssl/ca.pem
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
  • 拷贝文件到其他节点

    1
    2
    3
    4
    5
    
    scp -r /opt/etcd master-02:/opt/
    scp -r /opt/etcd master-03:/opt/
    
    scp /usr/lib/systemd/system/etcd.service master-02:/usr/lib/systemd/system/
    scp /usr/lib/systemd/system/etcd.service master-03:/usr/lib/systemd/system/
  • 修改其他两个节点的配置文件

    修改其余两个节点的 /opt/etcd/cfg/etcd.conf 配置文件,把里面相关的IP改成本机的 IP

    1
    2
    3
    4
    5
    
    ETCD_NAME=
    ETCD_LISTEN_PEER_URLS=
    ETCD_LISTEN_CLIENT_URLS=
    ETCD_INITIAL_ADVERTISE_PEER_URLS=
    ETCD_ADVERTISE_CLIENT_URLS=
  • 启动服务

    1
    2
    
    systemctl daemon-reload
    systemctl enable --now etcd
  • 查看集群健康状态

    1
    2
    3
    4
    5
    6
    7
    8
    
    # --endpoints:指定要连接的etcd集群节点的协议、地址和端口;
    # --cacert:指定用于验证etcd服务器证书的CA证书的路径,CA证书用于验证etcd服务器证书的有效性;
    # --cert:指定用于与etcd服务器进行通信的客户端证书的路径,客户端证书用于在与etcd服务器建立安全通信时进行身份验证;
    # --key:指定与客户端证书配对的私钥的路径,私钥用于对通信进行加密解密和签名验证;
    # endpoint health:子命令,用于检查etcd集群的健康状态;
    # --write-out:指定以表格形式输出结果;
    
    /opt/etcd/bin/etcdctl --endpoints="10.203.0.11:2379,10.203.0.12:2379,10.203.0.13:2379" --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/etcd.pem --key=/opt/etcd/ssl/etcd-key.pem  endpoint status --write-out=table

    image-20250104203338573

    如果所有节点 HEALTH 为 true,则表示 etcd 集群部署成功

  • 查看集群节点信息

    1
    
    /opt/etcd/bin/etcdctl --endpoints="10.203.0.11:2379,10.203.0.12:2379,10.203.0.13:2379" --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/etcd.pem --key=/opt/etcd/ssl/etcd-key.pem  endpoint status --write-out=table endpoint health

    image-20250104203504655

使用 cfssl 为 k8s 各组件生成自签证书(在 master-01 上操作)

  • 创建存放证书的目录

    1
    
    mkdir -p /data/k8s/kubernetes && cd /data/k8s/kubernetes
  • 创建 ca-config.json 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    # 配置加密和认证签名的一些参数,让CA软件知道颁发什么样的证书
    # 分为两个部分:signing和profiles
    # signing部分包含了默认签名配置和配置文件
    # 默认签名配置default指定了证书的过期时间为876000h,表示证书有效期为100年
    # profiles部分定义了不同的证书配置文件
    # 在这里,只有一个配置文件kubernetes。它包含了以下usages和过期时间expiry
    # 1. signing:表示该证书可用于签名其它证书
    # 2. key encipherment:表示该证书用于加密和解密传输数据
    # 3. server auth:表示client可以使用该CA对server提供的证书进行验证
    # 4. client auth:表示server可以使用该CA对client提供的证书进行验证
    # 5. 对于配置文件etcd,证书的过期时间也是876000h,表示证书有效期为100年
    
    cat > ca-config.json << EOF
    {
      "signing": {
        "default": {
          "expiry": "876000h"
        },
        "profiles": {
          "kubernetes": {
             "usages": [
                "signing",
                "key encipherment",
                "server auth",
                "client auth"
            ],
            "expiry": "876000h"
          }
        }
      }
    }
    EOF
  • 创建 ca-csr.json 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    # 这是一个用于生成Kubernetes相关证书的配置文件。该配置文件中包含以下信息
    # - "CN": CommonName,即用于标识证书的通用名称。在此配置中,CN设置为"Kubernetes",表示该证书是用于Kubernetes。
    # - "key": {} 指定了生成证书所使用的密钥的配置信息。"algo": "rsa" 指定了密钥的算法为RSA,"size": 2048 指定了密钥的长度为2048位。
    # - "names": [] 包含了生成证书时所需的实体信息。在这个例子中,只包含了一个实体,其相关信息如下:
    #   - C:Country,即国家。在此配置中,设置为 "CN"。
    #   - ST:State,即省/州。在此配置中,设置为 "LiaoNing"。
    #   - L:Locality,即城市。在此配置中,设置为 "DaLian"。
    #   - O:Organization,即组织。在此配置中,设置为 "Kubernetes"。
    #   - OU:Organization Unit,即组织单位。在此配置中,设置为 "Kubernetes-manual",表示手动管理的Kubernetes集群。
    # - "ca": {} 指定了生成证书时所需的CA(Certificate Authority)配置信息。
    #   - "expiry": "876000h" 指定了证书的有效期,这里是876000小时,即100年
    # 生成证书签名请求时,可以使用这个JSON配置文件作为输入,根据配置文件中的信息生成相应的CSR文件。然后,可以将CSR文件发送给CA进行签名,以获得有效的证书。
    # 这个配置文件用于生成Kubernetes相关的证书,以确保集群中的通信安全性。
    
    cat > ca-csr.json << EOF
    {
        "CN": "kubernetes",
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "ST": "LiaoNing",
                "L": "DaLian",
                "O": "Kubernetes",
                "OU": "Kubernetes-manual"
            }
        ],
        "ca": {
        "expiry": "876000h"
      }
    }
    EOF
  • 生成 CA 证书和私钥

    1
    2
    3
    4
    5
    6
    
    # cfssl是一个用于生成TLS/SSL证书的工具,它支持PKI、JSON格式配置文件以及与许多其他集成工具的配合使用。
    # gencert参数表示生成证书的操作。-initca参数表示初始化一个CA(证书颁发机构)。CA是用于签发其他证书的根证书。ca-csr.json是一个JSON格式的配置文件,其中包含了CA的详细信息,如私钥、公钥、有效期等。这个文件提供了生成CA证书所需的信息。
    # | 为管道符,表示将上一个命令的输出作为下一个命令的输入。
    # cfssljson是cfssl工具的一个子命令,用于格式化cfssl生成的JSON数据。-bare参数表示直接输出裸证书,即只生成证书文件,不包含其他格式的文件。ca是指定生成的证书文件的路径和文件名前缀。
    # 所以,这条命令的作用是使用cfssl工具根据配置文件ca-csr.json生成一个CA证书,并将证书文件保存在当前路径下,证书文件名前缀为ca,实际生成的文件名为ca.csr、ca.pem、ca-key.pem。
    cfssl gencert -initca ca-csr.json | cfssljson -bare ca
  • 创建 kube-apiserver 证书

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    # 这是一个JSON格式的配置文件,用于生成一个证书签名请求(Certificate Signing Request,CSR)。
    # 首先,"CN"字段指定了该证书的通用名称(Common Name),这里设为"kube-apiserver",表示该证书用于Kubernetes API Server。
    # 其次,"hosts"字段指定该证书的授权范围,包括apiserver节点IP、负载均衡器节点IP地址、VIP地址、Kubernetes服务IP和域名。
    # 其中Kubernetes服务IP是apiserver自动创建的,一般是--service-cluster-ip-range参数指定的网段的第一个IP地址(本例中为10.0.0.1),--service-cluster-ip-range参数在kube-apiserver.conf和kube-controller-manager.conf中配置
    # 127.0.0.1不要修改
    # 默认Kubernetes域名后缀为cluster.local,如果要使用非默认域名如koenli.net,需要修改域名列表中的最后两个域名为kubernetes.default.svc.koenli、kubernetes.default.svc.koenli.net
    # 接下来,"key"字段指定了密钥的算法("algo"字段)和长度("size"字段),此处使用的是RSA算法,密钥长度为2048位。
    # 最后,"names"字段是一个数组,其中包含了一个名字对象,用于指定证书中的一些其他信息。这个名字对象包含了以下字段:
    # - "C"字段指定了国家代码(Country),这里设置为"CN"。
    # - "ST"字段指定了省份(State)或地区,这里设置为"LiaoNing"。
    # - "L"字段指定了城市(Locality),这里设置为"DaLian"。
    # - "O"字段指定了组织(Organization),这里设置为"Kubernetes"。
    # - "OU"字段指定了组织单元(Organizational Unit),这里设置为"Kubernetes-manual",表示手动管理的Kubernetes集群。
    # 这些字段将作为证书的一部分,用于标识和验证证书的使用范围和颁发者等信息。
    # 这个配置文件可以用于生成Kubernetes相关的证书,以确保集群中的通信安全性。
    cat > apiserver-csr.json << EOF
    {
        "CN": "kube-apiserver",
        "hosts": [
          "127.0.0.1",
          "10.0.0.1",
          "kubernetes",
          "kubernetes.default",
          "kubernetes.default.svc",
          "kubernetes.default.svc.cluster",
          "kubernetes.default.svc.cluster.local",
          "10.203.0.11",
          "10.203.0.12",
          "10.203.0.13",
          "10.203.0.10"
        ],
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "ST": "LiaoNing",
                "L": "DaLian",
                "O": "Kubernetes",
                "OU": "Kubernetes-manual"
            }
        ]
    }
    EOF
    
    # 为Kubernetes API Server生成自签证书
    # -ca=ca.pem:指定证书的颁发机构(CA)文件路径;
    # -ca-key=ca-key.pem:指定证书的颁发机构(CA)私钥文件路径;
    # -config=ca-config.json:指定CA配置文件的路径,该文件定义了证书的有效期、加密算法等设置;
    # -profile=kubernetes:指定使用的证书配置文件,该文件定义了证书的用途和扩展属性;
    # apiserver-csr.json:指定API Server的证书签名请求配置文件路径;
    # | cfssljson -bare apiserver:通过管道符将cfssl命令的输出传递给cfssljson命令,并使用-bare参数直接输出裸证书,即只生成证书文件,不包含其他格式的文件,最后指定证书文件名前缀为apiserver,实际生成的文件名为apiserver.csr、apiserver.pem、apiserver-key.pem;
    # 所以,这个命令将会生成API Server的证书和私钥,并保存到指定的文件中。
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes apiserver-csr.json | cfssljson -bare apiserver
  • 生成 apiserver 聚合证书

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    # 创建front-proxy-ca-csr.json文件
    cat > front-proxy-ca-csr.json  << EOF 
    {
      "CN": "front-proxy-ca",
      "key": {
         "algo": "rsa",
         "size": 2048
      },
      "ca": {
        "expiry": "876000h"
      }
    }
    EOF
    
    # 生成apiserver聚合CA证书和私钥
    cfssl gencert -initca front-proxy-ca-csr.json | cfssljson -bare front-proxy-ca
    
    
    # 创建front-proxy-client-csr.json文件
    cat > front-proxy-client-csr.json  << EOF 
    {
      "CN": "front-proxy-client",
      "hosts": [""],
      "key": {
         "algo": "rsa",
         "size": 2048
      }
    }
    EOF
    
    # 生成用于Kubernetes的front-proxy-client证书
    cfssl gencert -ca=front-proxy-ca.pem -ca-key=front-proxy-ca-key.pem -config=ca-config.json -profile=kubernetes front-proxy-client-csr.json | cfssljson -bare front-proxy-client
  • 生成 kube-Controller-manager 证书

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    # 创建kube-controller-manager-csr.json文件
    cat > kube-controller-manager-csr.json << EOF
    {
      "CN": "system:kube-controller-manager",
      "hosts": [""],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "LiaoNing",
          "L": "DaLian",
          "O": "system:kube-controller-manager",
          "OU": "Kubernetes-manual"
        }
      ]
    }
    EOF
    
    # 为kube-controller-manager生成自签证书
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
  • 生成 kube-scheduler 证书

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    # 创建kube-scheduler-csr.json文件
    cat > kube-scheduler-csr.json << EOF
    {
      "CN": "system:kube-scheduler",
      "hosts": [""],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "LiaoNing",
          "L": "DaLian",
          "O": "system:kube-scheduler",
          "OU": "Kubernetes-manual"
        }
      ]
    }
    EOF
    
    # 为kube-scheduler生成自签证书
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
  • 生成 admin 证书

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    # 创建admin-csr.json文件
    cat > admin-csr.json << EOF
    {
      "CN": "admin",
      "hosts": [""],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "LiaoNing",
          "L": "DaLian",
          "O": "system:masters",
          "OU": "Kubernetes-manual"
        }
      ]
    }
    EOF
    
    # 为kubectl生成自签证书
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
  • 生成 kube-proxy 证书

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    # 创建kube-proxy-csr.json文件
    cat > kube-proxy-csr.json << EOF
    {
      "CN": "system:kube-proxy",
      "hosts": [""],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "LiaoNing",
          "L": "DaLian",
          "O": "system:kube-proxy",
          "OU": "Kubernetes-manual"
        }
      ]
    }
    EOF
    
    
    # 为kube-proxy生成自签证书
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
  • 创建 ServiceAccount Key —secret

    1
    2
    
    openssl genrsa -out /data/k8s/kubernetes/sa.key 2048
    openssl rsa -in /data/k8s/kubernetes/sa.key -pubout -out /data/k8s/kubernetes/sa.pub

在 10.203.0.10 上部署 Nginx 负载均衡

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 安装 Nginx 和 stream 模块
yum install nginx nginx-mod-stream

# 配置
vim /etc/nginx/nginx.conf

stream {
  upstream k8s {
    server 10.203.0.11:6443;
    server 10.203.0.12:6443;
    server 10.203.0.13:6443;
  }
  
  server {
    listen 0.0.0.0:6443;
    proxy_pass k8s;
  }
}

# 启动服务
systemctl enable --now nginx

部署 master 组件(在 master-01 上操作)

  • 创建目录

    1
    
    mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
  • 下载 kubernetes 安装包

    1
    
    wget https://dl.k8s.io/v1.31.1/kubernetes-server-linux-amd64.tar.gz
  • 解压安装包到 /opt/kubernetes/bin/ 目录下

    1
    
    tar -xf kubernetes-server-linux-amd64.tar.gz  --strip-components=3 -C /opt/kubernetes/bin kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy}
  • 拷贝自签证书到 /etc/kubernetes/ssl/ 目录下

    1
    2
    
    cp /data/k8s/kubernetes/*pem /opt/kubernetes/ssl/
    cp /data/k8s/kubernetes/sa* /opt/kubernetes/ssl/
  • 创建 kube-apiserver 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    
    cat > /opt/kubernetes/cfg/kube-apiserver.conf << EOF
    KUBE_APISERVER_OPTS="--v=2 \\
    --allow-privileged=true \\
    # 修改为本机 IP
    --bind-address=10.203.0.11 \\
    --secure-port=6443 \\
    # 修改为本机 IP
    --advertise-address=10.203.0.11 \\
    --service-cluster-ip-range=10.0.0.0/24 \\
    --service-node-port-range=30000-32767 \\
    --etcd-servers=https://10.203.0.11:2379,https://10.203.0.12:2379,https://10.203.0.13:2379 \\
    --etcd-cafile=/opt/etcd/ssl/ca.pem \\
    --etcd-certfile=/opt/etcd/ssl/etcd.pem \\
    --etcd-keyfile=/opt/etcd/ssl/etcd-key.pem \\
    --client-ca-file=/opt/kubernetes/ssl/ca.pem \\
    --tls-cert-file=/opt/kubernetes/ssl/apiserver.pem  \\
    --tls-private-key-file=/opt/kubernetes/ssl/apiserver-key.pem \\
    --kubelet-client-certificate=/opt/kubernetes/ssl/apiserver.pem \\
    --kubelet-client-key=/opt/kubernetes/ssl/apiserver-key.pem \\
    --service-account-key-file=/opt/kubernetes/ssl/sa.pub \\
    --service-account-signing-key-file=/opt/kubernetes/ssl/sa.key \\
    --service-account-issuer=https://kubernetes.default.svc.cluster.local \\
    --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota \\
    --authorization-mode=RBAC,Node \\
    --enable-bootstrap-token-auth=true \\
    --requestheader-client-ca-file=/opt/kubernetes/ssl/front-proxy-ca.pem \\
    --proxy-client-cert-file=/opt/kubernetes/ssl/front-proxy-client.pem \\
    --proxy-client-key-file=/opt/kubernetes/ssl/front-proxy-client-key.pem \\
    --requestheader-allowed-names=aggregator \\
    --requestheader-group-headers=X-Remote-Group \\
    --requestheader-extra-headers-prefix=X-Remote-Extra- \\
    --requestheader-username-headers=X-Remote-User \\
    --enable-aggregator-routing=true \\
    --token-auth-file=/opt/kubernetes/cfg/token.csv \\
    --audit-log-maxage=30 \\
    --audit-log-maxbackup=3 \\
    --audit-log-maxsize=100 \\
    --audit-log-path=/opt/kubernetes/logs/k8s-audit.log \\
    --default-not-ready-toleration-seconds=20 \\
    --default-unreachable-toleration-seconds=20"
    EOF
  • 创建 kube-controller-manager 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    cat > /opt/kubernetes/cfg/kube-controller-manager.conf << EOF
    KUBE_CONTROLLER_MANAGER_OPTS="--v=2 \\
    --bind-address=127.0.0.1 \\
    --root-ca-file=/opt/kubernetes/ssl/ca.pem \\
    --cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \\
    --cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \\
    --service-account-private-key-file=/opt/kubernetes/ssl/sa.key \\
    --kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \\
    --leader-elect=true \\
    --use-service-account-credentials=true \\
    --node-monitor-grace-period=20s \\
    --node-monitor-period=2s \\
    --controllers=*,bootstrapsigner,tokencleaner \\
    --allocate-node-cidrs=true \\
    --service-cluster-ip-range=10.0.0.0/24 \\
    --cluster-cidr=10.244.0.0/16 \\
    --requestheader-client-ca-file=/opt/kubernetes/ssl/front-proxy-ca.pem \\
    --cluster-signing-duration=876000h0m0s \\
    --node-startup-grace-period=20s \\
    --node-eviction-rate=1"
    EOF
  • 生成 kube-controller-manager 访问 apiserver 的 kubeconfig 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    
    # KUBE_APISERVER地址修改为实际环境apiserver的IP:Port或VIP:Port
    KUBE_CONFIG="/opt/kubernetes/cfg/kube-controller-manager.kubeconfig"
    KUBE_APISERVER="https://10.203.0.10:6443"
    
    # kubectl config set-cluster命令用于配置集群信息。
    # --certificate-authority选项指定了集群的证书颁发机构(CA)的路径,这个CA会验证kube-apiserver提供的证书是否合法。
    # --embed-certs选项用于将证书嵌入到生成的kubeconfig文件中,这样就不需要在kubeconfig文件中单独指定证书文件路径。
    # --server选项指定kube-apiserver的地址。
    # --kubeconfig选项指定生成的kubeconfig文件的路径和名称。
    # 综上所述,kubectl config set-cluster命令的作用是在kubeconfig文件中设置集群信息,包括证书颁发机构、证书、kube-apiserver地址等。
    /opt/kubernetes/bin/kubectl config set-cluster kubernetes \
      --certificate-authority=/opt/kubernetes/ssl/ca.pem \
      --embed-certs=true \
      --server=${KUBE_APISERVER} \
      --kubeconfig=${KUBE_CONFIG}
    
    # 配置Kubernetes控制器管理器的上下文信息
    # 1. kubectl config set-context system:kube-controller-manager@kubernetes: 设置上下文的名称为`ystem:kube-controller-manager@kubernetes,这是一个标识符,用于唯一标识该上下文。
    # 2. --cluster=kubernetes: 指定集群的名称为kubernetes,这是一个现有集群的标识符,表示要管理的Kubernetes集群。
    # 3. --user=system:kube-controller-manager: 指定使用的用户身份为system:kube-controller-manager。这是一个特殊的用户身份,具有控制 Kubernetes控制器管理器的权限。
    # 4. --kubeconfig选项指定生成的kubeconfig文件的路径和名称。kubeconfig文件是一个用于管理Kubernetes配置的文件,包含了集群、用户和上下文的相关信息。
    # 通过运行这个命令,可以将这些配置信息保存到/opt/kubernetes/cfg/kube-controller-manager.kubeconfig文件中,以便在后续的操作中使用。
    /opt/kubernetes/bin/kubectl config set-context system:kube-controller-manager@kubernetes \
      --cluster=kubernetes \
      --user=system:kube-controller-manager \
      --kubeconfig=${KUBE_CONFIG}
    
    #  设置一个用户项
    # 以下命令是用于设置Kubernetes的controller-manager组件的客户端凭据。下面是每个参数的详细解释:
    # - kubectl config: 是使用kubectl命令行工具的配置子命令。
    # - set-credentials: 是定义一个新的用户凭据配置的子命令。
    # - system:kube-controller-manager: 是设置用户凭据的名称,system:是Kubernetes API Server内置的身份验证器使用的用户标识符前缀,它表示是一个系统用户,在本例中是kube-controller-manager组件使用的身份。
    # - --client-certificate=./kube-controller-manager.pem: 指定kube-controller-manager.pem客户端证书的路径。
    # - --client-key=./kube-controller-manager-key.pem: 指定kube-controller-manager-key.pem客户端私钥的路径。
    # - --embed-certs=true: 表示将证书和私钥直接嵌入到生成的kubeconfig文件中,而不是通过引用外部文件。
    # - --kubeconfig选项指定生成的kubeconfig文件的路径和名称。
    # 通过运行上述命令,将根据提供的证书和私钥信息,为kube-controller-manager创建一个kubeconfig文件,以便后续使用该文件进行身份验证和访问 Kubernetes API。
    /opt/kubernetes/bin/kubectl config set-credentials system:kube-controller-manager \
      --client-certificate=/opt/kubernetes/ssl/kube-controller-manager.pem \
      --client-key=/opt/kubernetes/ssl/kube-controller-manager-key.pem \
      --embed-certs=true \
      --kubeconfig=${KUBE_CONFIG}
    
    # 设置默认环境
    # 设置kubectl使用指定的上下文环境来执行操作。上下文环境是kubectl用来确定要连接到哪个Kubernetes集群以及使用哪个身份验证信息的配置。
    # 在这个命令中,kubectl config use-context是用来设置当前上下文环境的命令。system:kube-controller-manager@kubernetes是指定的上下文名称,它告诉kubectl要使用的Kubernetes集群和身份验证信息。
    # --kubeconfig选项指定生成的kubeconfig文件的路径和名称。kubeconfig文件是存储集群连接和身份验证信息的配置文件。
    # 通过执行这个命令,kubectl将使用指定的上下文来执行后续的操作,包括部署和管理Kubernetes资源。
    /opt/kubernetes/bin/kubectl config use-context system:kube-controller-manager@kubernetes \
         --kubeconfig=${KUBE_CONFIG}
  • 创建 kube-scheduler 配置文件

    1
    2
    3
    4
    5
    6
    
    cat > /opt/kubernetes/cfg/kube-scheduler.conf << EOF
    KUBE_SCHEDULER_OPTS="--v=2 \\
    --bind-address=127.0.0.1 \\
    --leader-elect=true \\
    --kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
    EOF
  • 生成 kube-scheduler 访问 apiserver 的 kubeconfig 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    # KUBE_APISERVER地址修改为实际环境apiserver的IP:Port或VIP:Port
    KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
    KUBE_APISERVER="https://10.203.0.10:6443"
    
    /opt/kubernetes/bin/kubectl config set-cluster kubernetes \
      --certificate-authority=/opt/kubernetes/ssl/ca.pem \
      --embed-certs=true \
      --server=${KUBE_APISERVER} \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-credentials system:kube-scheduler \
      --client-certificate=/opt/kubernetes/ssl/kube-scheduler.pem \
      --client-key=/opt/kubernetes/ssl/kube-scheduler-key.pem \
      --embed-certs=true \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-context system:kube-scheduler@kubernetes \
      --cluster=kubernetes \
      --user=kube-scheduler \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config use-context system:kube-scheduler@kubernetes --kubeconfig=${KUBE_CONFIG}
  • 创建 kube-apiserver 的 systemd 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    cat > /usr/lib/systemd/system/kube-apiserver.service << EOF
    [Unit]
    Description=Kubernetes API Server
    Documentation=https://github.com/kubernetes/kubernetes
    
    [Service]
    EnvironmentFile=/opt/kubernetes/cfg/kube-apiserver.conf
    ExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS
    Restart=on-failure
    
    [Install]
    WantedBy=multi-user.target
    EOF
  • 创建 kube-controller-manager 的 systemd 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF
    [Unit]
    Description=Kubernetes Controller Manager
    Documentation=https://github.com/kubernetes/kubernetes
    
    [Service]
    EnvironmentFile=/opt/kubernetes/cfg/kube-controller-manager.conf
    ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
    Restart=on-failure
    
    [Install]
    WantedBy=multi-user.target
    EOF
  • 创建 kube-scheduler 的 systemd 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    cat > /usr/lib/systemd/system/kube-scheduler.service << EOF
    [Unit]
    Description=Kubernetes Scheduler
    Documentation=https://github.com/kubernetes/kubernetes
    
    [Service]
    EnvironmentFile=/opt/kubernetes/cfg/kube-scheduler.conf
    ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
    Restart=on-failure
    
    [Install]
    WantedBy=multi-user.target
    EOF
  • 创建 token.csv 文件

    1
    2
    3
    4
    
    # 随机生成一个32位字符串
    token=`head -c 16 /dev/urandom | od -An -t x | tr -d ' '`
    echo "$token,kubelet-bootstrap,10001,'system:node-bootstrapper'" > /opt/kubernetes/cfg/token.csv
    # token.csv文件的格式为:(第一列)随机字符串,(第二列)用户名,(第三列)UID,(第四列)用户组
  • 拷贝文件到其他节点

    1
    2
    3
    4
    5
    
    scp -r /opt/kubernetes master-02:/opt/
    scp -r /opt/kubernetes master-03:/opt/
    
    scp /usr/lib/systemd/system/kube-{apiserver,controller-manager,scheduler}.service master-02:/usr/lib/systemd/system/
    scp /usr/lib/systemd/system/kube-{apiserver,controller-manager,scheduler}.service master-03:/usr/lib/systemd/system/
  • 修改其他节点的配置文件

    1
    2
    3
    
    # 把其他两个节点的 /opt/kubernetes/cfg/kube-apiserver.conf 中的以下参数改为本机 IP
    --bind-address=
    --advertise-address=
  • 所有 master 节点执行以下命令启动服务

    1
    2
    3
    4
    5
    6
    7
    
    systemctl daemon-reload
    
    systemctl enable --now kube-apiserver
    
    systemctl enable --now kube-controller-manager
    
    systemctl enable --now kube-scheduler
  • 生成 kubectl 访问集群的 kubeconfig 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    mkdir /root/.kube
    
    # 生成kubectl访问apiserver的kubeconfig配置文件
    # 以下是Shell命令,直接在终端执行
    # KUBE_APISERVER地址修改为实际环境apiserver的IP:Port或VIP:Port
    KUBE_CONFIG="/root/.kube/config"
    KUBE_APISERVER="https://10.203.0.10:6443"
    
    /opt/kubernetes/bin/kubectl config set-cluster kubernetes \
      --certificate-authority=/opt/kubernetes/ssl/ca.pem \
      --embed-certs=true \
      --server=${KUBE_APISERVER} \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-credentials kubernetes-admin \
      --client-certificate=/opt/kubernetes/ssl/admin.pem \
      --client-key=/opt/kubernetes/ssl/admin-key.pem \
      --embed-certs=true \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-context kubernetes-admin@kubernetes \
      --cluster=kubernetes \
      --user=kubernetes-admin \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config use-context kubernetes-admin@kubernetes --kubeconfig=${KUBE_CONFIG}
    
    # 把 .kube 目录拷贝到其他两个节点上
    scp -r /root/.kube master-02:/root/
    scp -r /root/.kube master-03:/root/
  • 在任意一个节点执行以下命令授权 kubelet-bootstrap 用户允许请求证书

    1
    
    /opt/kubernetes/bin/kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

至此,三节点的 master 高可用集群部署完成


部署 node 节点

node 工作节点只需要以下几个组件:

  • kubelet
  • kube-proxy
  • 容器运行时 - containerd

部署 containerd 容器(在所有 node 节点操作)

  • 安装 cni 插件

    1
    2
    3
    4
    5
    6
    
    # 下载
    wget https://github.com/containernetworking/plugins/releases/download/v1.6.1/cni-plugins-linux-amd64-v1.6.1.tgz
    
    # 解压
    mkdir -p /etc/cni/net.d /opt/cni/bin
    tar xf cni-plugins-linux-amd64-v1.6.1.tgz -C /opt/cni/bin/
  • 安装 cri 插件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    # 下载
    wget https://github.com/containerd/containerd/releases/download/v1.7.13/cri-containerd-cni-1.7.13-linux-amd64.tar.gz
    
    # 解压
    tar xf cri-containerd-cni-1.7.13-linux-amd64.tar.gz -C /
    
    # 创建 systemd 文件
    cat > /etc/systemd/system/containerd.service <<EOF
    [Unit]
    Description=containerd container runtime
    Documentation=https://containerd.io
    After=network.target local-fs.target
    
    [Service]
    ExecStartPre=-/sbin/modprobe overlay
    ExecStart=/usr/local/bin/containerd
    Type=notify
    Delegate=yes
    KillMode=process
    Restart=always
    RestartSec=5
    LimitNPROC=infinity
    LimitCORE=infinity
    LimitNOFILE=infinity
    TasksMax=infinity
    OOMScoreAdjust=-999
    
    [Install]
    WantedBy=multi-user.target
    EOF
  • 配置模块

    1
    2
    3
    4
    5
    6
    7
    8
    
    # 配置模块
    cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
    overlay
    br_netfilter
    EOF
    
    # 加载模块
    systemctl restart systemd-modules-load
  • 创建 containerd 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    # 创建默认配置文件
    mkdir -p /etc/containerd
    containerd config default | tee /etc/containerd/config.toml
    
    
    # 修改配置文件
    sed -i "s#SystemdCgroup\ \=\ false#SystemdCgroup\ \=\ true#g" /etc/containerd/config.toml
    
    sed -i "s#registry.k8s.io#k8s.m.daocloud.io#g" /etc/containerd/config.toml
    
    sed -i "s#config_path\ \=\ \"\"#config_path\ \=\ \"/etc/containerd/certs.d\"#g" /etc/containerd/config.toml
    
    
    # 配置加速器
    mkdir /etc/containerd/certs.d/docker.io -pv
    
    cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
    server = "https://docker.io"
    [host."https://hub.valueonline.cn"]
      capabilities = ["pull", "resolve"]
    EOF
  • 配置 containerd 客户端

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    # 下载
    wget https://mirrors.chenby.cn/https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-amd64.tar.gz
    
    # 解压
    tar xf crictl-v1.29.0-linux-amd64.tar.gz -C /usr/bin/
    
    # 生成配置文件
    cat > /etc/crictl.yaml <<EOF
    runtime-endpoint: unix:///run/containerd/containerd.sock
    image-endpoint: unix:///run/containerd/containerd.sock
    timeout: 10
    debug: false
    EOF
    
    # 测试
    systemctl daemon-reload && systemctl enable --now containerd
    crictl info
  • 安装 runc

    1
    2
    3
    
    wget https://github.com/opencontainers/runc/releases/download/v1.1.9/runc.amd64
    chmod +x runc.amd64
    mv runc.amd64 /usr/local/bin/runc

部署 kubelet (在所有 node 节点上操作)

  • 创建目录

    1
    
    mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
  • 从 master-01 节点拷贝二进制文件

    1
    2
    
    scp /opt/kubernetes/bin/{kubelet,kube-proxy} node-01:/opt/kubernetes/bin/
    scp /opt/kubernetes/bin/{kubelet,kube-proxy} node-02:/opt/kubernetes/bin/
  • 创建 kubelet.conf 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    cat > /opt/kubernetes/cfg/kubelet.conf << EOF
    KUBELET_OPTS="--v=2 \\
    --hostname-override=node-01 \\			# 修改成本机的主机名
    --bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
    --kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
    --config=/opt/kubernetes/cfg/kubelet-config.yml \\
    --cert-dir=/opt/kubernetes/ssl \\
    --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9 \\
    --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
    EOF
  • 创建 kubelet-config.yml 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    cat > /opt/kubernetes/cfg/kubelet-config.yml << EOF
    kind: KubeletConfiguration
    apiVersion: kubelet.config.k8s.io/v1beta1
    address: 0.0.0.0
    port: 10250
    readOnlyPort: 10255
    cgroupDriver: systemd
    clusterDNS:
    - 10.0.0.2
    clusterDomain: cluster.local 
    failSwapOn: false
    authentication:
      anonymous:
        enabled: false
      webhook:
        cacheTTL: 2m0s
        enabled: true
      x509:
        clientCAFile: /opt/kubernetes/ssl/ca.pem 
    authorization:
      mode: Webhook
      webhook:
        cacheAuthorizedTTL: 5m0s
        cacheUnauthorizedTTL: 30s
    evictionHard:
      imagefs.available: 15%
      memory.available: 100Mi
      nodefs.available: 10%
      nodefs.inodesFree: 5%
    maxOpenFiles: 1000000
    maxPods: 110
    EOF
  • 创建 kube-proxy.conf 文件

    1
    2
    3
    4
    
    cat > /opt/kubernetes/cfg/kube-proxy.conf << EOF
    KUBE_PROXY_OPTS="--v=2 \\
    --config=/opt/kubernetes/cfg/kube-proxy-config.yml"
    EOF
  • 创建 kube-proxy-config.yml 配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    cat > /opt/kubernetes/cfg/kube-proxy-config.yml << EOF
    kind: KubeProxyConfiguration
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    bindAddress: 0.0.0.0
    metricsBindAddress: 0.0.0.0:10249
    clientConnection:
      kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfig
    hostnameOverride: node-01		# 修改成本机的主机名
    clusterCIDR: 10.0.0.0/24
    mode: ipvs
    ipvs:
      scheduler: "rr"
    iptables:
      masqueradeAll: true
    EOF
  • 创建 kubelet 的 systemd 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    cat > /usr/lib/systemd/system/kubelet.service << EOF
    [Unit]
    Description=Kubernetes Kubelet
    After=docker.service
    Wants=docker.service
    
    [Service]
    EnvironmentFile=/opt/kubernetes/cfg/kubelet.conf
    ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
  • 创建 kube-proxy 的 systemd 文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    cat > /usr/lib/systemd/system/kube-proxy.service << EOF
    [Unit]
    Description=Kubernetes Proxy
    After=network.target
    
    [Service]
    EnvironmentFile=/opt/kubernetes/cfg/kube-proxy.conf
    ExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS
    Restart=on-failure
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    EOF
  • 生成 bootstrap.kubeconfig 配置文件(在 master 节点上操作)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    # 在安装了cfssl工具的主机(建议用master1)上生成 bootstrap.kubeconfig 配置文件
    KUBE_CONFIG="/opt/kubernetes/cfg/bootstrap.kubeconfig"
    KUBE_APISERVER="https://10.203.0.10:6443"
    TOKEN="f9025a9a825236acdf1089d6744776aa"
    
    /opt/kubernetes/bin/kubectl config set-cluster kubernetes \
      --certificate-authority=/opt/kubernetes/ssl/ca.pem \
      --embed-certs=true \
      --server=${KUBE_APISERVER} \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-credentials kubelet-bootstrap \
      --token=${TOKEN} \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-context kubelet-bootstrap@kubernetes \
      --cluster=kubernetes \
      --user=kubelet-bootstrap \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config use-context kubelet-bootstrap@kubernetes --kubeconfig=${KUBE_CONFIG}
    
    # 将bootstrap.kubeconfig文件拷贝到所有node节点上
    scp /opt/kubernetes/cfg/bootstrap.kubeconfig node-01:/opt/kubernetes/cfg/
    scp /opt/kubernetes/cfg/bootstrap.kubeconfig node-02:/opt/kubernetes/cfg/
  • 生成 kube-proxy.kubeconfig 配置文件(在 master 节点上操作)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    # 在安装了cfssl工具的主机(建议用master1)上生成kube-proxy.kubeconfig配置文件
    KUBE_CONFIG="/opt/kubernetes/cfg/kube-proxy.kubeconfig"
    KUBE_APISERVER="https://10.203.0.10:6443"
    
    /opt/kubernetes/bin/kubectl config set-cluster kubernetes \
      --certificate-authority=/opt/kubernetes/ssl/ca.pem \
      --embed-certs=true \
      --server=${KUBE_APISERVER} \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-credentials kube-proxy \
      --client-certificate=/opt/kubernetes/ssl/kube-proxy.pem \
      --client-key=/opt/kubernetes/ssl/kube-proxy-key.pem \
      --embed-certs=true \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config set-context kube-proxy@kubernetes \
      --cluster=kubernetes \
      --user=kube-proxy \
      --kubeconfig=${KUBE_CONFIG}
    
    /opt/kubernetes/bin/kubectl config use-context kube-proxy@kubernetes --kubeconfig=${KUBE_CONFIG}
    
    # 将kube-proxy.kubeconfig文件拷贝到所有node节点上
    scp /opt/kubernetes/cfg/kube-proxy.kubeconfig node-01:/opt/kubernetes/cfg/
    scp /opt/kubernetes/cfg/kube-proxy.kubeconfig node-02:/opt/kubernetes/cfg/
  • 从 master-01 上拷贝 自签证书和私钥到所有 node 节点上

    1
    2
    
    scp /opt/kubernetes/ssl/{ca,kube-proxy,kube-proxy-key}.pem node-01:/opt/kubernetes/ssl/
    scp /opt/kubernetes/ssl/{ca,kube-proxy,kube-proxy-key}.pem node-02:/opt/kubernetes/ssl/
  • 启动服务并设置开机自启

    1
    2
    3
    4
    
    systemctl daemon-reload
    
    systemctl enable --now kubelet
    systemctl enable --now kube-proxy
  • 允许给 node 颁发证书

    当 kubelet 和 kube-proxy 启动成功后,此时在任意一台 master 节点上执行 kubectl get csr 可以看到有新的节点请求颁发证书 (CONDITION 字段处于 Pending 状态)

    image-20250104230022570

    执行以下命令允许给 Node 颁发证书

    1
    2
    
    # node-csr-xxxxxx替换成执行kubectl get csr查询到的节点NAME值,多个用空格隔开
    /opt/kubernetes/bin/kubectl certificate approve node-csr-0JAFjdykoL4qfzREgD8mudCX8oMXZKQmY1nvgSqIC8s

    授权颁发证书后,在任意一台 master 节点执行 kubectl get node 能看到 node 节点都处于 NotReady 状态,这是因为还没有安装网络插件