云原生架构之【Kubernetes(K8s)】第三部分:多主控高可用集群部署

本方案基于 CentOS8 系统设计,建议在 RedHat/CentOS 系统中使用。

目录

1.部署拓扑图
2.操作系统初始化
3.证书服务器的安装和配置
4.Etcd 数据库集群部署
5.Master 主控集群部署
-- 5.1.第一个 Master 主控节点部署
-- 5.2.其他 Master 主控节点部署
6.Master 高可用集群部署
-- 6.1.Nginx 安装和配置
-- 6.2.Keepalived 安装和配置
7.Node 工作集群部署
8.CNI 容器网络(Flannel 插件)部署
9.DNS 域名发现(CoreDNS 插件)部署
10.用户管理界面(Dashboard 插件)部署


1.部署拓扑图

K8s Master 高可用集群拓扑图

网络资源规划:

1、Master 主控节点

节点名 主机名 IP 地址 程序 操作系统
主控节点-1 k8s-master1 192.168.0.21 kube-apiserver,kube-controllermanager,kube-scheduler CentOS8
主控节点-2 k8s-master2 192.168.0.22 kube-apiserver,kube-controllermanager,kube-scheduler CentOS8
主控节点≥3 k8s-master3 192.168.0.23 kube-apiserver,kube-controllermanager,kube-scheduler CentOS8

2、Master 高可用节点

节点名 主机名 IP:PORT 程序 操作系统
高可用节点-1 k8s-proxy1 192.168.0.11 Nginx,Keepalived CentOS8
高可用节点≥2 k8s-proxy2 192.168.0.12 Nginx,Keepalived CentOS8

Keepalived Virtual IP:192.168.0.10。

3、Node 工作节点

节点名 主机名 IP 地址 程序 操作系统
工作节点-1 k8s-node1 192.168.0.31 kubelet,kube-proxy,docker CentOS8
工作节点-2 k8s-node2 192.168.0.32 kubelet,kube-proxy,docker CentOS8
工作节点≥3 k8s-node3 192.168.0.33 kubelet,kube-proxy,docker CentOS8

4、Etcd 节点

节点名 主机名 IP 地址 程序 操作系统
Etcd 节点-1 k8s-etcd1 192.168.0.41 etcd CentOS8
Etcd 节点-2 k8s-etcd2 192.168.0.42 etcd CentOS8
Etcd 节点≥3 k8s-etcd3 192.168.0.43 etcd CentOS8

5、SSL 证书服务器

  • 主机名:k8s-ssl
  • IP:192.168.0.50
  • 程序:CFSSL,OpenSSL
  • 操作系统:CentOS8

6、K8s 集群网络

  • Service 子网 IP 段:10.0.0.0/16。用于为 Pod 中发布的服务自动分配 IP 地址。
  • CNI 子网 IP 段:10.254.0.0/16。用于为 Pod 中部署的容器自动分配 IP 地址。

2.操作系统初始化

以 "主控节点" 为例,初始化各个主控节点、主控高可用节点、工作节点、Etcd 节点的操作系统配置(主控高可用节点跳过第 3 步和第 7 步):

1、关闭防火墙。

[centos@k8s-master1 ~]$ sudo systemctl stop firewalld.service
[centos@k8s-master1 ~]$ sudo systemctl disable firewalld.service

2、关闭 SELinux。

1)临时关闭 SELinux。

[centos@k8s-master1 ~]$ sudo setenforce 0

2)修改 SELinux 配置文件,永久关闭 SELinux。

使用文本编辑器打开"/etc/selinux/config"文件:

[centos@k8s-master1 ~]$ sudo gedit /etc/selinux/config

将 "SELINUX" 参数设置为:"disabled",并保存:

# enforcing - 表示启用 SELinux 安全策略。
# permissive - 表示启用 SELinux 安全策略,但不强制验证。如果执行第一步可以正常运行,则建议设置此值。
# disabled - 关闭 SELinux 安全策略,相当于没有安装 SELinux。
SELINUX=disabled

3、关闭 Swap(虚拟内存)。

1)临时关闭 Swap。

[centos@k8s-master1 ~]$ sudo swapoff -a

2)修改挂载配置文件,永久关闭 Swap。

使用文本编辑器打开"/etc/fstab"文件:

[centos@k8s-master1 ~]$ sudo gedit /etc/fstab

注释掉 Swap 的挂载配置,并保存:

# UUID=0b0d1b60-ff0c-450b-b842-e9e2669839b1 swap                    swap    defaults        0 0

4、设置各节点的系统的时区和时间保持一致,可以通过时间服务器同步,也可以手动设置。

1)设置时区为 "中国上海":

[centos@k8s-master1 ~]$ sudo timedatectl set-timezone Asia/Shanghai

2)设置时间同步配置:

使用文本编辑器打开"/etc/chrony.conf"文件:

[centos@k8s-master1 ~]$ sudo gedit /etc/chrony.conf

验证或修改以下配置并保存:

# 其中【2.centos.pool.ntp.org】是时间服务器地址
pool 2.centos.pool.ntp.org iburst

5、设置主机名。

1)临时设置主机名。

[centos@k8s-master1 ~]$ sudo hostnamectl set-hostname k8s-master1 && bash

2)修改主机名配置文件,永久配置主机名。

使用文本编辑器打开"/etc/hostname"文件:

[centos@k8s-master1 ~]$ sudo gedit /etc/hostname

修改主机名并保存:

k8s-master1

6、设置静态 IP 地址。

设置静态 IP 地址

7、设置本地 DNS 配置,将 IP 地址和主机名进行映射。

使用文本编辑器打开"/etc/hosts"文件:

[centos@k8s-master1 ~]$ sudo gedit /etc/hosts

在文件中追加各个节点的 IP 和 hostname 映射记录并保存:

192.168.0.11 k8s-proxy1
192.168.0.12 k8s-proxy2
192.168.0.21 k8s-master1
192.168.0.22 k8s-master2
192.168.0.23 k8s-master3
192.168.0.31 k8s-node1
192.168.0.32 k8s-node2
192.168.0.33 k8s-node3
192.168.0.41 k8s-etcd1
192.168.0.42 k8s-etcd2
192.168.0.43 k8s-etcd3

8、重启操作系统,永久适配以上配置。

[centos@k8s-master1 ~]$ sudo reboot

3.证书服务器的安装和配置

Etcd 和 API Server 通过 Https 协议提供接口,因此在部署 Etcd 和 API Server 时需要使用 SSL 证书,CFSSL 是一款开源的证书管理工具,它使用 JSON 文件描述证书的元数据,并通过命令行创建自签名证书。

证书管理工具的安装以及证书颁发、管理可以在任意主机上实施,Etcd 和 API Server 只使用最终它创建的私钥和证书文件。“主机”可以是集群中的任意节点或者集群外的专用证书管理服务器均可。

以在 "SSL 证书服务器" 上安装证书工具及实施证书颁发、管理为例:

1、打开 CFSSL 下载页面【https://pkg.cfssl.org/】,下载最新版本的 cfssl、cfssljson 和 cfssl-certinfo 的编译程序文件到用户主目录中。

CFSSL 下载页面

cfssl:用于创建证书;
cfssljson:用于通过 JSON 元数据文件创建证书;
cfssl-certinfo:用于查看证书内容。

2、为 CFSSL 的程序文件增加可执行权限。

[centos@k8s-ssl ~]$ chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64

3、将 CFSSL 的程序文件迁移安装到操作系统默认的 shell 目录中并重命名。

[centos@k8s-ssl ~]$ sudo mv cfssl_linux-amd64 /usr/bin/cfssl
[centos@k8s-ssl ~]$ sudo mv cfssljson_linux-amd64 /usr/bin/cfssljson
[centos@k8s-ssl ~]$ sudo mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

4、验证程序。

[centos@k8s-ssl ~]$ cfssl

5、创建 SSL 工作目录,更改所有者账号。

[centos@k8s-ssl ~]$ sudo mkdir -p /data/ssl
[centos@k8s-ssl ~]$ sudo chown -R centos:centos /data/ssl

6、制作 K8s 的 CA 根证书。

1)创建 K8s 的 CA 根证书目录:

[centos@k8s-ssl ~]$ mkdir -p /data/ssl/k8s/ca

2)创建 K8s 的 CA 根证书 的 JSON 配置文件:

使用文本编辑器创建 "/data/ssl/k8s/ca/ca-config.json" 文件:

[centos@k8s-ssl ~]$ gedit /data/ssl/k8s/ca/ca-config.json

编辑配置内容并保存(删除注释):

{
  "signing": {
    # 通用策略。
    "default": {
      # 表示过期时间,【h】 表示时间单位为 【小时】。
      "expiry": "87600h"
    },
    "profiles": {
      # 表示该配置的用途是为 kubernetes 生成证书及相关的认证工作 。
      "k8s": {
        # 表示 kubernetes 配置的过期时间。
        "expiry": "87600h",
        "usages": [
          # 表示该证书可用于签名其它证书,也就是 CA 根证书。
          "signing",
          "key encipherment",
          # 表示可以该 CA 对 Server 提供的证书进行认证。
          "server auth",
          # 表示可以该 CA 对 Client 提供的证书进行认证。
          "client auth"
        ]
      }
    }
  }
}

3)创建 K8s 的 CA 根证书申请 的 JSON 配置文件:

使用文本编辑器创建 "/data/ssl/k8s/ca/ca-csr.json" 文件:

[centos@k8s-ssl ~]$ gedit /data/ssl/k8s/ca/ca-csr.json

编辑配置内容并保存(删除注释):

{
  # 证书名称
  "CN": "ca",
  # 证书加密算法
  "key": {
    # 秘钥算法
    "algo": "rsa",
    # 秘钥长度
    "size": 2048
  },
  # 证书颁发机构名称
  "names": [
    {
      # 国家名称
      "C": "cn",
      # 省份名称
      "ST": "sd",
      # 城市名称
      "L": "qd",
      # 组织机构名称
      "O": "private",
      # 组织单元名称
      "OU": "zhangyi"
    }
  ]
}

4)进入 CA 根证书目录,生成 K8s 的 CA 根证书CA 秘钥

[centos@k8s-ssl ~]$ cd /data/ssl/k8s/ca
[centos@k8s-ssl ca]$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

2020/08/17 15:28:59 [INFO] generating a new CA key and certificate from CSR
2020/08/17 15:28:59 [INFO] generate received request
2020/08/17 15:28:59 [INFO] received CSR
2020/08/17 15:28:59 [INFO] generating key: rsa-2048
2020/08/17 15:28:59 [INFO] encoded CSR
2020/08/17 15:28:59 [INFO] signed certificate with serial number 116577353254406726865056466732539458431685116104

[centos@k8s-ssl ca]$ ll *.pem
-rw------- 1 centos centos 1675 8月  17 15:28 ca-key.pem
-rw-rw-r-- 1 centos centos 1346 8月  17 15:28 ca.pem

7、制作 K8s 的 Etcd 证书。

1)创建 K8s 的 Etcd 证书目录:

[centos@k8s-ssl ~]$ mkdir -p /data/ssl/k8s/etcd

2)创建 K8s 的 Etcd 证书申请 的 JSON 配置文件:

使用文本编辑器创建 "/data/ssl/k8s/etcd/etcd-csr.json" 文件:

[centos@k8s-ssl ~]$ gedit /data/ssl/k8s/etcd/etcd-csr.json

编辑配置内容并保存(删除注释):

{
  # 证书名称
  "CN": "etcd",
  # Etcd 集群中所有节点的 IP 或 DNS
  "hosts": [
    "127.0.0.1",
    "192.168.0.41",
    "192.168.0.42",
    "192.168.0.43",
    "localhost"
  ],
  # 证书加密算法
  "key": {
    # 秘钥算法
    "algo": "rsa",
    # 秘钥长度
    "size": 2048
  },
  "names": [
    {
      # 国家名称
      "C": "cn",
      # 省份名称
      "ST": "sd",
      # 城市名称
      "L": "qd",
      # 组织机构名称
      "O": "private",
      # 组织单元名称
      "OU": "zhangyi"
    }
  ]
}

3)进入 Etcd 证书目录,调用 CA 根证书,生成 K8s 的 Etcd 证书Etcd 证书秘钥

[centos@k8s-ssl ~]$ cd /data/ssl/k8s/etcd
[centos@k8s-ssl etcd]$ cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -profile=k8s etcd-csr.json | cfssljson -bare etcd

2020/08/17 16:07:20 [INFO] generate received request
2020/08/17 16:07:20 [INFO] received CSR
2020/08/17 16:07:20 [INFO] generating key: rsa-2048
2020/08/17 16:07:20 [INFO] encoded CSR
2020/08/17 16:07:20 [INFO] signed certificate with serial number 245573148699245996773294161637542724002482924968
2020/08/17 16:07:20 [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").

[centos@k8s-ssl etcd]$ ll *.pem
-rw------- 1 centos centos 1675 8月  17 16:07 etcd-key.pem
-rw-rw-r-- 1 centos centos 1428 8月  17 16:07 etcd.pem

8、制作 K8s 的 Server 证书。

1)创建 K8s 的 Server 证书目录:

[centos@k8s-ssl ~]$ mkdir -p /data/ssl/k8s/server

2)创建 K8s 的 Server 证书申请 的 JSON 配置文件:

使用文本编辑器创建 "/data/ssl/k8s/server/server-csr.json" 文件:

[centos@k8s-ssl ~]$ gedit /data/ssl/k8s/server/server-csr.json

编辑配置内容并保存(删除注释):

{
  # 证书名称,同时也是 K8s Server 的 API Server、Controller Manager 的服务端账号。
  "CN": "kubernetes",
  # 包含所有 Master 节点的 IP 和 DNS,以及 Master 高可用节点的 IP 和 Virtual IP(设置为空或不设置该属性时不会对域名进行限制,但是降低了安全性)。
  "hosts": [
    "127.0.0.1",
    "10.0.0.1",
    "192.168.0.21",
    "192.168.0.22",
    "192.168.0.23",
    "192.168.0.11",
    "192.168.0.12",
    "192.168.0.10",
    "localhost",
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local"
  ],
  # 证书加密算法
  "key": {
    # 秘钥算法
    "algo": "rsa",
    # 秘钥长度
    "size": 2048
  },
  "names": [
    {
      # 国家名称
      "C": "cn",
      # 省份名称
      "ST": "sd",
      # 城市名称
      "L": "qd",
      # 组织机构名称
      "O": "private",
      # 组织单元名称
      "OU": "zhangyi"
    }
  ]
}

3)进入 Server 证书目录,调用 CA 根证书,生成 K8s 的 Server 证书Server 证书秘钥

[centos@k8s-ssl ~]$ cd /data/ssl/k8s/server
[centos@k8s-ssl server]$ cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -profile=k8s server-csr.json | cfssljson -bare server

2020/08/17 16:18:33 [INFO] generate received request
2020/08/17 16:18:33 [INFO] received CSR
2020/08/17 16:18:33 [INFO] generating key: rsa-2048
2020/08/17 16:18:33 [INFO] encoded CSR
2020/08/17 16:18:33 [INFO] signed certificate with serial number 436972371201156087194456890942017146190769381451
2020/08/17 16:18:33 [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").

[centos@k8s-ssl server]$ ll *.pem
-rw------- 1 centos centos 1675 8月  17 16:18 server-key.pem
-rw-rw-r-- 1 centos centos 1419 8月  17 16:18 server.pem

9、制作 K8s 的 Proxy 客户端证书(用于 K8s 内置的 Proxy 客户端账号 system:kube-proxy 访问 API Server)。

1)创建 K8s 的 Proxy 证书目录:

[centos@k8s-ssl ~]$ mkdir -p /data/ssl/k8s/proxy

2)创建 K8s 的 Proxy 证书申请 的 JSON 配置文件:

使用文本编辑器创建 "/data/ssl/k8s/proxy/proxy-csr.json" 文件:

[centos@k8s-ssl ~]$ gedit /data/ssl/k8s/proxy/proxy-csr.json

编辑配置内容并保存(删除注释):

{
  # 证书名称,同时也是 K8s 内置的 Proxy 客户端账号。
  "CN": "system:kube-proxy",
  "hosts": [],
  # 证书加密算法
  "key": {
    # 秘钥算法
    "algo": "rsa",
    # 秘钥长度
    "size": 2048
  },
  "names": [
    {
      # 国家名称
      "C": "cn",
      # 省份名称
      "ST": "sd",
      # 城市名称
      "L": "qd",
      # 组织机构名称
      "O": "private",
      # 组织单元名称
      "OU": "zhangyi"
    }
  ]
}

3)进入 Proxy 证书目录,调用 CA 根证书,生成 K8s 的 Proxy 证书Proxy 证书秘钥

[centos@k8s-ssl ~]$ cd /data/ssl/k8s/proxy
[centos@k8s-ssl proxy]$ cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -profile=k8s proxy-csr.json | cfssljson -bare proxy

2020/08/20 10:52:03 [INFO] generate received request
2020/08/20 10:52:03 [INFO] received CSR
2020/08/20 10:52:03 [INFO] generating key: rsa-2048
2020/08/20 10:52:03 [INFO] encoded CSR
2020/08/20 10:52:03 [INFO] signed certificate with serial number 438353289881924064412254168935174700007379178723
2020/08/20 10:52:03 [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").

[centos@k8s-ssl proxy]$ ll *.pem
-rw------- 1 centos centos 1679 8月  20 10:52 proxy-key.pem
-rw-rw-r-- 1 centos centos 1387 8月  20 10:52 proxy.pem

4.Etcd 数据库集群部署

Etcd 是一个分布式键值存储系统,K8s 使用 Etcd 进行数据存储。为避免 Etcd 单点故障,建议采用集群方式部署,集群中 Etcd 节点的数量以 ≥ 3 个的单数为宜。

以 "Etcd 节点-1" 为例,所有 "Etcd 节点" 都需实施以下操作:

1、打开 Etcd 下载页面【https://github.com/etcd-io/etcd/releases】,下载最新版本 Etcd 的编译程序 tar 包到用户主目录中。

Etcd 下载页面

2、解压缩编译程序 tar 包到"/usr/local"目录中。

[centos@k8s-etcd1 ~]$ sudo tar zxvf etcd-v3.4.10-linux-amd64.tar.gz -C /usr/local
[centos@k8s-etcd1 ~]$ sudo mv /usr/local/etcd-v3.4.10-linux-amd64 /usr/local/etcd-v3.4.10
[centos@k8s-etcd1 ~]$ sudo chown -R root:root /usr/local/etcd-v3.4.10
[centos@k8s-etcd1 ~]$ ll /usr/local
drwxr-xr-x  3 root root 123 7月  17 06:43 etcd-v3.4.10

3、创建 Etcd 数据目录并设置权限,Etcd 在启动时会检查数据目录权限,数据目录权限必须设置为 "rwx------"。

[centos@k8s-etcd1 ~]$ sudo mkdir -p /data/etcd
[centos@k8s-etcd1 ~]$ sudo chmod 700 /data/etcd

4、创建 Etcd 秘钥目录,并从 SSL 证书服务器上获取已创建的 CA 根证书,Etcd 证书和 Etcd 证书秘钥 。

1)创建 Etcd 秘钥目录:

[centos@k8s-etcd1 ~]$ sudo mkdir -p /usr/local/etcd-v3.4.10/ssl

2)使用 ssh 远程登录到 SSL 证书服务器,并将 SSL 证书服务器上已制作好的 CA 根证书,Etcd 证书和 Etcd 证书秘钥通过 scp 拷贝到 "Etcd 节点-1"(当前主机) 的 Etcd 秘钥目录中:

[centos@k8s-etcd1 ~]$ ssh centos@192.168.0.50
centos@192.168.0.50's password:
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/ca/ca.pem root@192.168.0.41:/usr/local/etcd-v3.4.10/ssl
root@192.168.0.41's password:
ca.pem                                                                              100% 1346     1.7MB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/etcd/etcd.pem root@192.168.0.41:/usr/local/etcd-v3.4.10/ssl
root@192.168.0.41's password:
etcd.pem                                                                            100% 1428    43.5KB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/etcd/etcd-key.pem root@192.168.0.41:/usr/local/etcd-v3.4.10/ssl
root@192.168.0.41's password:
etcd-key.pem                                                                        100% 1675     1.6MB/s   00:00
[centos@k8s-ssl ~]$ exit

[centos@k8s-etcd1 ~]$ sudo chmod 644 /usr/local/etcd-v3.4.10/ssl/*
[centos@k8s-etcd1 ~]$ ll /usr/local/etcd-v3.4.10/ssl
-rw-r--r-- 1 root root 1346 8月  18 11:27 ca.pem
-rw-r--r-- 1 root root 1675 8月  18 11:30 etcd-key.pem
-rw-r--r-- 1 root root 1428 8月  18 11:29 etcd.pem

5、创建并编辑 Etcd 启动参数配置文件。

使用文本编辑器创建 "/usr/local/etcd-v3.4.10/etcd.conf" 文件:

[centos@k8s-etcd1 ~]$ sudo gedit /usr/local/etcd-v3.4.10/etcd.conf

编辑配置内容并保存(删除注释):

# 节点配置
# 节点的名称,同一集群中节点名称是唯一的。
NAME="etcd-1"
# 节点的数据目录。
DATA_DIR="/data/etcd"
# 节点的内部通信监听地址清单(逗号分隔),用于集群内部通信。
LISTEN_PEER_URLS="https://0.0.0.0:2380"
# 节点的客户端服务监听地址清单(逗号分隔),用于对外提供数据服务。
LISTEN_CLIENT_URLS="https://0.0.0.0:2379"

# 集群配置
# 为集群中其他节点提供的,用于和本节点进行内部通信的地址清单(逗号分隔),一般是当前节点的内部通信监听地址。
INITIAL_ADVERTISE_PEER_URLS="https://192.168.0.41:2380"
# 为集群中其他节点提供的,用于访问本节点数据服务的地址清单(逗号分隔),一般是当前节点的客户端服务监听地址。
ADVERTISE_CLIENT_URLS="https://192.168.0.41:2379"
# 集群中所有节点的内部通信监听地址清单(逗号分隔)。
INITIAL_CLUSTER="etcd-1=https://192.168.0.41:2380,etcd-2=https://192.168.0.42:2380,etcd-3=https://192.168.0.43:2380"
# 集群标识符,用于区分不同的集群,同一集群的节点应设置相同的值。
INITIAL_CLUSTER_TOKEN="etcd-cluster"
# 用于指示本次是否为新建集群。可选值包括:new 和 existing 。设置为 existing 则该节点启动时会尝试与其他节点交互。集群初次建立时应设置为 new;集群运行中当节点故障后进行恢复时设置为 existing 或者 new。
INITIAL_CLUSTER_STATE="new"

6、配置 Etcd 服务并设置开机自启动。

使用文本编辑器创建配置文件:

[centos@k8s-etcd1 ~]$ sudo gedit /usr/lib/systemd/system/etcd.service

编写文件内容并保存如下:

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
User=root
Group=root
EnvironmentFile=-/usr/local/etcd-v3.4.10/etcd.conf
ExecStart=/usr/local/etcd-v3.4.10/etcd \
          --name=${NAME} \
          --data-dir=${DATA_DIR} \
          --listen-peer-urls=${LISTEN_PEER_URLS} \
          --listen-client-urls=${LISTEN_CLIENT_URLS} \
          --initial-advertise-peer-urls=${INITIAL_ADVERTISE_PEER_URLS} \
          --advertise-client-urls=${ADVERTISE_CLIENT_URLS} \
          --initial-cluster=${INITIAL_CLUSTER} \
          --initial-cluster-token=${INITIAL_CLUSTER_TOKEN} \
          --initial-cluster-state=${INITIAL_CLUSTER_STATE} \
          # 用于客户端请求的证书文件
          --cert-file=/usr/local/etcd-v3.4.10/ssl/etcd.pem \
          # 用于客户端请求的秘钥文件
          --key-file=/usr/local/etcd-v3.4.10/ssl/etcd-key.pem \
          # 用于客户端请求的受信任的 CA 证书文件
          --trusted-ca-file=/usr/local/etcd-v3.4.10/ssl/ca.pem \
          # 用于内部通信请求的证书文件
          --peer-cert-file=/usr/local/etcd-v3.4.10/ssl/etcd.pem \
          # 用于内部通信请求的秘钥文件
          --peer-key-file=/usr/local/etcd-v3.4.10/ssl/etcd-key.pem \
          # 用于内部通信请求的受信任的 CA 证书文件
          --peer-trusted-ca-file=/usr/local/etcd-v3.4.10/ssl/ca.pem \
          --logger=zap
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

设置开机启动:

[centos@k8s-etcd1 ~]$ sudo systemctl daemon-reload
[centos@k8s-etcd1 ~]$ sudo systemctl enable etcd.service

注意:其他"Etcd 节点"上全部需要按照以上步骤配置。

7、依次启动各 Etcd 节点的 Etcd 服务。Etcd 集群至少需要两个以上节点正常启动才能运行,因此第一个 Etcd 节点启动时会处于挂起等待状态,挂起状态会在第二个 Etcd 节点启动后恢复,或者在长时间未发现第二个 Etcd 节点时超时退出。

[centos@k8s-etcd1 ~]$ sudo systemctl start etcd.service
[centos@k8s-etcd1 ~]$ sudo systemctl status etcd.service

8、在任意 Etcd 节点上查看 Etcd 集群健康。

[centos@k8s-etcd1 ~]$ ETCDCTL_API=3 
[centos@k8s-etcd1 ~]$ /usr/local/etcd-v3.4.10/etcdctl --cacert=/usr/local/etcd-v3.4.10/ssl/ca.pem --cert=/usr/local/etcd-v3.4.10/ssl/etcd.pem --key=/usr/local/etcd-v3.4.10/ssl/etcd-key.pem --endpoints="https://192.168.0.41:2379,https://192.168.0.42:2379,https://192.168.0.43:2379" endpoint health --write-out=table

+---------------------------+--------+-------------+-------+
|         ENDPOINT          | HEALTH |    TOOK     | ERROR |
+---------------------------+--------+-------------+-------+
| https://192.168.0.41:2379 |   true | 13.851824ms |       |
| https://192.168.0.42:2379 |   true | 14.336573ms |       |
| https://192.168.0.43:2379 |   true | 23.145602ms |       |
+---------------------------+--------+-------------+-------+

9、Etcd 集群运维。

1)查看集群节点健康:

[centos@k8s-etcd1 ~]$ ETCDCTL_API=3 
[centos@k8s-etcd1 ~]$ /usr/local/etcd-v3.4.10/etcdctl --cacert=/usr/local/etcd-v3.4.10/ssl/ca.pem --cert=/usr/local/etcd-v3.4.10/ssl/etcd.pem --key=/usr/local/etcd-v3.4.10/ssl/etcd-key.pem --endpoints="https://192.168.0.41:2379,https://192.168.0.42:2379,https://192.168.0.43:2379" endpoint health --write-out=table

+---------------------------+--------+-------------+-------+
|         ENDPOINT          | HEALTH |    TOOK     | ERROR |
+---------------------------+--------+-------------+-------+
| https://192.168.0.41:2379 |   true | 13.851824ms |       |
| https://192.168.0.42:2379 |   true | 14.336573ms |       |
| https://192.168.0.43:2379 |   true | 23.145602ms |       |
+---------------------------+--------+-------------+-------+

2)查看集节点群状态:

[centos@k8s-etcd1 ~]$ ETCDCTL_API=3 
[centos@k8s-etcd1 ~]$ /usr/local/etcd-v3.4.10/etcdctl --cacert=/usr/local/etcd-v3.4.10/ssl/ca.pem --cert=/usr/local/etcd-v3.4.10/ssl/etcd.pem --key=/usr/local/etcd-v3.4.10/ssl/etcd-key.pem --endpoints="https://192.168.0.41:2379,https://192.168.0.42:2379,https://192.168.0.43:2379" endpoint status --write-out=table

+---------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|         ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+---------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://192.168.0.41:2379 | 97feb1a73a325656 |  3.4.10 |  651 kB |      true |      false |         7 |        867 |                867 |        |
| https://192.168.0.42:2379 | fa4ddfec63d549fc |  3.4.10 |  655 kB |     false |      false |         7 |        867 |                867 |        |
| https://192.168.0.43:2379 | ec67af24a94fb07c |  3.4.10 |  668 kB |     false |      false |         7 |        867 |                867 |        |
+---------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

3)查看集节点成员清单:

[centos@k8s-etcd1 ~]$ ETCDCTL_API=3 
[centos@k8s-etcd1 ~]$ /usr/local/etcd-v3.4.10/etcdctl --cacert=/usr/local/etcd-v3.4.10/ssl/ca.pem --cert=/usr/local/etcd-v3.4.10/ssl/etcd.pem --key=/usr/local/etcd-v3.4.10/ssl/etcd-key.pem --endpoints="https://192.168.0.41:2379,https://192.168.0.42:2379,https://192.168.0.43:2379" member list --write-out=table

+------------------+---------+--------+---------------------------+---------------------------+------------+
|        ID        | STATUS  |  NAME  |        PEER ADDRS         |       CLIENT ADDRS        | IS LEARNER |
+------------------+---------+--------+---------------------------+---------------------------+------------+
| 97feb1a73a325656 | started | etcd-1 | https://192.168.0.41:2380 | https://192.168.0.41:2379 |      false |
| ec67af24a94fb07c | started | etcd-3 | https://192.168.0.42:2380 | https://192.168.0.42:2379 |      false |
| fa4ddfec63d549fc | started | etcd-2 | https://192.168.0.43:2380 | https://192.168.0.43:2379 |      false |
+------------------+---------+--------+---------------------------+---------------------------+------------+

4)移除一个节点成员:

[centos@k8s-etcd1 ~]$ ETCDCTL_API=3 
[centos@k8s-etcd1 ~]$ /usr/local/etcd-v3.4.10/etcdctl --cacert=/usr/local/etcd-v3.4.10/ssl/ca.pem --cert=/usr/local/etcd-v3.4.10/ssl/etcd.pem --key=/usr/local/etcd-v3.4.10/ssl/etcd-key.pem --endpoints="https://192.168.0.41:2379,https://192.168.0.42:2379,https://192.168.0.43:2379" member remove 97feb1a73a325656

Member 97feb1a73a325656 removed from cluster 8f957fc90dd9f6bc

5.Master 主控集群部署

5.1.第一个 Master 主控节点部署

在第一个 Master 主控节点上执行以下操作步骤,以 "k8s-master1" 为例:

1、打开 K8s 下载页面【https://github.com/kubernetes/kubernetes/releases】,下载最新版本 Kubernetes Server 的编译程序 tar 包到用户主目录中。

注意:Kubernetes Server 的 tar 包中包含了:Master 主控节点,Node 工作节点和客户端的全部程序。

第一步,点击链接进入编译程序下载页面
第二步,下载 Kubernetes Server 的 tar 包

2、解压缩编译程序 tar 包到"/usr/local"目录中,并为管理工具创建系统 Shell 目录的软链接。

1)解压缩编译程序 tar 包到"/usr/local"目录中:

[centos@k8s-master1 ~]$ sudo tar zxvf kubernetes-server-linux-amd64.tar.gz -C /usr/local
[centos@k8s-master1 ~]$ ll /usr/local
drwxr-xr-x  4 root root  79 8月  14 00:53 kubernetes

安装目录:/usr/local/kubernetes/server
可执行程序目录:/usr/local/kubernetes/server/bin

2)为管理工具创建系统 Shell 目录的软链接:

[centos@k8s-master1 ~]$ sudo ln -s /usr/local/kubernetes/server/bin/kubectl /usr/bin/kubectl

3、创建 K8s Server 日志目录、秘钥目录和配置文件目录。

[centos@k8s-master1 ~]$ sudo mkdir -p /usr/local/kubernetes/server/{logs,ssl,etc}

4、从 SSL 证书服务器上获取已创建的 CA 根证书,Server 证书和 Server 证书秘钥 ,Etcd 证书和 Etcd 证书秘钥 。

使用 ssh 远程登录到 SSL 证书服务器,并将 SSL 证书服务器上已制作好的 CA 根证书,Server 证书和 Server 证书秘钥,Etcd 证书和 Etcd 证书秘钥通过 scp 拷贝到 "Master 主控节点"(当前主机) 的 K8s Server 秘钥目录中:

[centos@k8s-master1 ~]$ ssh centos@192.168.0.50
centos@192.168.0.50's password:
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/ca/ca.pem root@192.168.0.21:/usr/local/kubernetes/server/ssl
root@192.168.0.21's password:
ca.pem                                                                                        100% 1346     1.5MB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/ca/ca-key.pem root@192.168.0.21:/usr/local/kubernetes/server/ssl
root@192.168.0.21's password:
ca-key.pem                                                                                    100% 1675   850.9KB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/server/server.pem root@192.168.0.21:/usr/local/kubernetes/server/ssl
root@192.168.0.21's password:
server.pem                                                                                    100% 1419   510.0KB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/server/server-key.pem root@192.168.0.21:/usr/local/kubernetes/server/ssl
root@192.168.0.21's password:
server-key.pem                                                                                100% 1675     1.2MB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/etcd/etcd.pem root@192.168.0.21:/usr/local/kubernetes/server/ssl
root@192.168.0.21's password:
etcd.pem                                                                                      100% 1428     1.8MB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/etcd/etcd-key.pem root@192.168.0.21:/usr/local/kubernetes/server/ssl
root@192.168.0.21's password:
etcd-key.pem                                                                                  100% 1675     1.3MB/s   00:00
[centos@k8s-ssl ~]$ exit

[centos@k8s-master1 ~]$ sudo chmod 644 /usr/local/kubernetes/server/ssl/*
[centos@k8s-master1 ~]$ ll /usr/local/kubernetes/server/ssl
-rw-r--r-- 1 root root 1675 8月  19 09:58 server-key.pem
-rw-r--r-- 1 root root 1419 8月  19 09:58 server.pem
-rw-r--r-- 1 root root 1675 8月  19 10:43 ca-key.pem
-rw-r--r-- 1 root root 1346 8月  19 09:56 ca.pem
-rw-r--r-- 1 root root 1675 8月  19 10:02 etcd-key.pem
-rw-r--r-- 1 root root 1428 8月  19 10:02 etcd.pem

5、启用 TLS Bootstrapping 机制。

Master 节点的 API Server 启用 TLS 认证后,Node 节点上的 Kubelet 与 API Server 通信,需使用 CA 证书。当 Node 节点较多时,证书颁发工作量大且增加集群扩展复杂度,为此 K8s 引入了 TLS Bootstraping 机制,实现 Kubelet 以一个低权限用户自动向 API Server 申请证书,Kubelet 的证书由 API Server 动态签署。

在 Master 节点上创建 Token 文件,定义 Node 节点上 Kubelet 通过 Bootstrapping 机制申请证书的用户信息:

1)随机生成一个 Token 值:

[centos@k8s-master1 ~]$ head -c 16 /dev/urandom | od -An -t x | tr -d ' '
d682ded2c1468b8c6a16375b48a638ff

2)创建 Token 配置文件:

使用文本编辑器创建 "/usr/local/kubernetes/server/etc/token.csv" 文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/local/kubernetes/server/etc/token.csv

编辑配置内容并保存:

d682ded2c1468b8c6a16375b48a638ff,kubelet-bootstrap,10001,"system:nodebootstrapper"

6、创建并编辑 API Server 启动参数配置文件。

使用文本编辑器创建 "/usr/local/kubernetes/server/etc/kube-apiserver.conf" 文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/local/kubernetes/server/etc/kube-apiserver.conf

编辑配置内容并保存:

KUBE_APISERVER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/usr/local/kubernetes/server/logs \
--etcd-servers=https://192.168.0.41:2379,https://192.168.0.42:2379,https://192.168.0.43:2379 \
--bind-address=192.168.0.21 \
--insecure-port=8080 \
--secure-port=6443 \
--advertise-address=192.168.0.21 \
--allow-privileged=true \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth=true \
--token-auth-file=/usr/local/kubernetes/server/etc/token.csv \
--service-cluster-ip-range=10.0.0.0/16 \
--service-node-port-range=30000-32767 \
--service-account-key-file=/usr/local/kubernetes/server/ssl/ca-key.pem \
--tls-cert-file=/usr/local/kubernetes/server/ssl/server.pem  \
--tls-private-key-file=/usr/local/kubernetes/server/ssl/server-key.pem \
--client-ca-file=/usr/local/kubernetes/server/ssl/ca.pem \
--kubelet-client-certificate=/usr/local/kubernetes/server/ssl/server.pem \
--kubelet-client-key=/usr/local/kubernetes/server/ssl/server-key.pem \
--etcd-cafile=/usr/local/kubernetes/server/ssl/ca.pem \ 
--etcd-certfile=/usr/local/kubernetes/server/ssl/etcd.pem \
--etcd-keyfile=/usr/local/kubernetes/server/ssl/etcd-key.pem \
--audit-log-path=/usr/local/kubernetes/server/logs/k8s-audit.log"

参数说明:

  • --logtostderr:是否启用日志。
  • --v:日志记录等级,可选范围【0-8】,数值越大日志越详细。
  • --log-dir:日志文件存储目录。
  • --etcd-servers:Etcd 集群数据服务地址。
  • --bind-address:API Server 服务监听地址。
  • --insecure-port:API Server 服务监听端口。
  • --secure-port:API Server Https 服务监听端口。
  • --advertise-address:为集群中其他节点提供的,用于和本节点进行内部通信的地址,一般是当前节点的服务监听地址。
  • --allow-privileged:是否允许创建的容器使用 root 权限。
  • --enable-admission-plugins:启用的准入控制插件列表。
  • --authorization-mode:认证授权的模式,一般设置为启用RBAC授权和节点自管理。
  • --enable-bootstrap-token-auth:启用 TLS Bootstrap 机制(自动为加入集群的节点颁发证书)。
  • --token-auth-file: TLS Bootstrap 机制的配置文件。
  • --service-cluster-ip-range:服务的虚拟IP地址段。
  • --service-node-port-range:服务默认分配端口范围。
  • --service-account-key-file:对服务的账号进行认证的秘钥文件。
  • --tls-cert-file:客户端连接 API Server 的证书文件(使用 K8s 的 Server 证书)。
  • --tls-private-key-file:客户端连接 API Server 的证书秘钥文件(使用 K8s 的 Server 证书秘钥)。
  • --client-ca-file:客户端 API Server 的 CA 证书文件。
  • --kubelet-client-certificate:API Server 连接 Kubelet 证书文件。
  • --kubelet-client-key:API Server 连接 Kubelet 客户端证书秘钥文件。
  • --etcd-cafile:API Server连接 Etcd 的 CA 证书文件。
  • --etcd-certfile:API Server连接 Etcd 的证书文件。
  • --etcd-keyfile:API Server连接 Etcd 的证书秘钥文件。
  • --audit-log-path:审计日志文件存储位置。

7、配置 API Server 启动服务。

使用文本编辑器创建配置文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/lib/systemd/system/kube-apiserver.service

编写文件内容并保存如下:

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
User=root
Group=root
EnvironmentFile=/usr/local/kubernetes/server/etc/kube-apiserver.conf
ExecStart=/usr/local/kubernetes/server/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

8、启动 API Server 服务并设置开机自启动。

[centos@k8s-master1 ~]$ sudo systemctl daemon-reload
[centos@k8s-master1 ~]$ sudo systemctl start kube-apiserver.service
[centos@k8s-master1 ~]$ sudo systemctl enable kube-apiserver.service
[centos@k8s-master1 ~]$ sudo systemctl status kube-apiserver.service

9、授权允许 Token 文件中定义的用户和角色请求动态证书。

[centos@k8s-master1 ~]$ kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

10、创建并编辑 Controller Manager 启动参数配置文件。

使用文本编辑器创建 "/usr/local/kubernetes/server/etc/kube-controller-manager.conf" 文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/local/kubernetes/server/etc/kube-controller-manager.conf

编辑配置内容并保存:

KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/usr/local/kubernetes/server/logs \
--leader-elect=true \
--master=127.0.0.1:8080 \
--bind-address=127.0.0.1 \
--allocate-node-cidrs=true \
--cluster-cidr=10.254.0.0/16 \
--service-cluster-ip-range=10.0.0.0/16 \
--root-ca-file=/usr/local/kubernetes/server/ssl/ca.pem \
--service-account-private-key-file=/usr/local/kubernetes/server/ssl/ca-key.pem \
--cluster-signing-cert-file=/usr/local/kubernetes/server/ssl/ca.pem \
--cluster-signing-key-file=/usr/local/kubernetes/server/ssl/ca-key.pem \
--experimental-cluster-signing-duration=87600h0m0s"

参数说明:

  • --logtostderr:是否启用日志。
  • --v:日志记录等级,可选范围【0-8】,数值越大日志越详细。
  • --log-dir:日志文件存储目录。
  • --leader-elect:是否启用集群自动选举。
  • --master:API Server 的服务监听地址和端口,一般被节点本地调用,设置为 “127.0.0.1:8080”。
  • --bind-address:Controller Manager 服务监听地址,一般被节点本地调用,设置为 “127.0.0.1”。
  • --allocate-node-cidrs:是否允许启用 CNI 网络。
  • --cluster-cidr:Pod 的 CNI 网络地址段。
  • --service-cluster-ip-range:服务的虚拟IP地址段。
  • --root-ca-file:对服务的账号进行认证的证书文件。
  • --service-account-private-key-file:对服务的账号进行认证的证书秘钥文件。
  • --cluster-signing-cert-file:自动为 Kubelet 颁发的集群签名 CA 证书文件。
  • --cluster-signing-key-file:自动为 Kubelet 颁发的集群签名 CA 证书秘钥文件。
  • --experimental-cluster-signing-duration:自动 Kubelet 颁发的证书的有效期。

11、配置 Controller Manager 启动服务。

使用文本编辑器创建配置文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/lib/systemd/system/kube-controller-manager.service

编写文件内容并保存如下:

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service

[Service]
User=root
Group=root
EnvironmentFile=/usr/local/kubernetes/server/etc/kube-controller-manager.conf
ExecStart=/usr/local/kubernetes/server/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

12、启动 Controller Manager 服务并设置开机自启动。

[centos@k8s-master1 ~]$ sudo systemctl daemon-reload
[centos@k8s-master1 ~]$ sudo systemctl start kube-controller-manager.service
[centos@k8s-master1 ~]$ sudo systemctl enable kube-controller-manager.service
[centos@k8s-master1 ~]$ sudo systemctl status kube-controller-manager.service

13、创建并编辑 Scheduler 启动参数配置文件。

使用文本编辑器创建 "/usr/local/kubernetes/server/etc/kube-scheduler.conf" 文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/local/kubernetes/server/etc/kube-scheduler.conf

编辑配置内容并保存:

KUBE_SCHEDULER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/usr/local/kubernetes/server/logs \
--leader-elect=true \
--master=127.0.0.1:8080 \
--bind-address=127.0.0.1"

参数说明:

  • --logtostderr:是否启用日志。
  • --v:日志记录等级,可选范围【0-8】,数值越大日志越详细。
  • --log-dir:日志文件存储目录。
  • --leader-elect:是否启用集群自动选举。
  • --master:API Server 的服务监听地址和端口,一般被节点本地调用,设置为 “127.0.0.1:8080”。
  • --bind-address:Scheduler 服务监听地址,一般被节点本地调用,设置为 “127.0.0.1”。

14、配置 Scheduler 启动服务。

使用文本编辑器创建配置文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/lib/systemd/system/kube-scheduler.service

编写文件内容并保存如下:

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service

[Service]
User=root
Group=root
EnvironmentFile=/usr/local/kubernetes/server/etc/kube-scheduler.conf
ExecStart=/usr/local/kubernetes/server/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

15、启动 Scheduler 服务并设置开机自启动。

[centos@k8s-master1 ~]$ sudo systemctl daemon-reload
[centos@k8s-master1 ~]$ sudo systemctl start kube-scheduler.service
[centos@k8s-master1 ~]$ sudo systemctl enable kube-scheduler.service
[centos@k8s-master1 ~]$ sudo systemctl status kube-scheduler.service

16、查看集群状态。

[centos@k8s-master1 ~]$ kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-1               Healthy   {"health":"true"}   
etcd-2               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"}   

17、K8s Server 启动顺序。

启动 K8s Server 之前,应保证 Etcd 集群正常运行。启动顺序如下:

[centos@k8s-master1 ~]$ sudo systemctl daemon-reload
[centos@k8s-master1 ~]$ sudo systemctl start kube-apiserver.service
[centos@k8s-master1 ~]$ sudo systemctl start kube-controller-manager.service
[centos@k8s-master1 ~]$ sudo systemctl start kube-scheduler.service

18、授权 Master 主控节点的 API Server 访问 Node 工作集群的 Kubelet,主要用于在主控节点上对工作集群进行监控和运维。

1)创建并编辑授权文件:

使用文本编辑器创建 "/usr/local/kubernetes/server/etc/apiserver-to-kubelet-rbac.yml" 文件:

[centos@k8s-master1 ~]$ sudo gedit /usr/local/kubernetes/server/etc/apiserver-to-kubelet-rbac.yml

编辑配置内容并保存(删除注释):

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-apiserver-to-kubelet
rules:
  - apiGroups:
      - ""
    resources:
      - nodes/proxy
      - nodes/stats
      - nodes/log
      - nodes/spec
      - nodes/metrics
      - pods/log
    verbs:
      - "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:kube-apiserver
  namespace: ""
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kube-apiserver-to-kubelet
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: kubernetes

注意:【subjects.name】 属性值应与 K8s Server 的证书申请文件 "server-csr.json" 中的【CN】属性值保持一致。

2)部署授权文件:

[centos@k8s-master1 ~]$ kubectl apply -f /usr/local/kubernetes/server/etc/apiserver-to-kubelet-rbac.yml

clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created

5.2.其他 Master 主控节点部署

在其他 Master 主控节点上执行以下操作步骤,以 "k8s-master2" 为例:

1、打开 K8s 下载页面【https://github.com/kubernetes/kubernetes/releases】,下载最新版本 Kubernetes Server 的编译程序 tar 包到用户主目录中。

注意:Kubernetes Server 的 tar 包中包含了:Master 主控节点,Node 工作节点和客户端的全部程序。

第一步,点击链接进入编译程序下载页面
第二步,下载 Kubernetes Server 的 tar 包

2、解压缩编译程序 tar 包到"/usr/local"目录中,并为管理工具创建系统 Shell 目录的软链接。

1)解压缩编译程序 tar 包到"/usr/local"目录中:

[centos@k8s-master2 ~]$ sudo tar zxvf kubernetes-server-linux-amd64.tar.gz -C /usr/local
[centos@k8s-master2 ~]$ ll /usr/local
drwxr-xr-x  4 root root  79 8月  14 00:53 kubernetes

安装目录:/usr/local/kubernetes/server
可执行程序目录:/usr/local/kubernetes/server/bin

2)为管理工具创建系统 Shell 目录的软链接:

[centos@k8s-master2 ~]$ sudo ln -s /usr/local/kubernetes/server/bin/kubectl /usr/bin/kubectl

3、创建 K8s Server 日志目录、秘钥目录和配置文件目录。

[centos@k8s-master2 ~]$ sudo mkdir -p /usr/local/kubernetes/server/{logs,ssl,etc}

4、从第一个 Master 主控节点上获取配置文件、证书文件、启动文件 。

使用 ssh 远程登录到第一个 Master 主控节点,并将第一个 Master 主控节点已部署好的配置文件、证书文件、启动文件通过 scp 拷贝到当前节点的对应目录中:

1)使用 ssh 远程登录到第一个 Master 主控节点上:

[centos@k8s-master2 ~]$ ssh centos@192.168.0.21
centos@192.168.0.21's password:

2)从第一个 Master 主控节点的 "/usr/local/kubernetes/server/etc" 目录下拷贝 "token.csv"、"kube-apiserver.conf"、"kube-controller-manager.conf"、"kube-scheduler.conf" 配置文件到当前节点一致对应的目录下:

[centos@k8s-master1 ~]$ scp -r /usr/local/kubernetes/server/etc/token.csv root@192.168.0.22:/usr/local/kubernetes/server/etc
root@192.168.0.22's password:
token.csv                                                            100%   83    68.1KB/s   00:00

[centos@k8s-master1 ~]$ scp -r /usr/local/kubernetes/server/etc/kube-apiserver.conf root@192.168.0.22:/usr/local/kubernetes/server/etc
root@192.168.0.22's password:
kube-apiserver.conf                                                  100% 1306   450.7KB/s   00:00

[centos@k8s-master1 ~]$ scp -r /usr/local/kubernetes/server/etc/kube-controller-manager.conf root@192.168.0.22:/usr/local/kubernetes/server/etc
root@192.168.0.22's password:
kube-controller-manager.conf                                         100%  615    93.3KB/s   00:00

[centos@k8s-master1 ~]$ scp -r /usr/local/kubernetes/server/etc/kube-scheduler.conf root@192.168.0.22:/usr/local/kubernetes/server/etc
root@192.168.0.22's password:
kube-scheduler.conf                                                  100%  171    31.9KB/s   00:00

3)从第一个 Master 主控节点的 "/usr/local/kubernetes/server/ssl" 目录下拷贝所有 PEM 证书文件到当前节点一致对应的目录下:

[centos@k8s-master1 ~]$ scp -r /usr/local/kubernetes/server/ssl root@192.168.0.22:/usr/local/kubernetes/server
root@192.168.0.22's password:
ca-key.pem                                                           100% 1675   739.4KB/s   00:00    
ca.pem                                                               100% 1322     1.0MB/s   00:00    
server-key.pem                                                       100% 1675     1.6MB/s   00:00    
server.pem                                                           100% 1627   941.8KB/s   00:00    
etcd-key.pem                                                         100% 1675     1.6MB/s   00:00    
etcd.pem                                                             100% 1424     1.5MB/s   00:00    

4)从第一个 Master 主控节点的 "/usr/lib/systemd/system" 目录下拷贝所有启动配置文件到当前节点一致对应的目录下:

[centos@k8s-master1 ~]$ scp -r /usr/lib/systemd/system/kube-apiserver.service root@192.168.0.22:/usr/lib/systemd/system
root@192.168.0.22's password:
kube-apiserver.service                                               100%  333   202.1KB/s   00:00

[centos@k8s-master1 ~]$ scp -r /usr/lib/systemd/system/kube-controller-manager.service root@192.168.0.22:/usr/lib/systemd/system
root@192.168.0.22's password:
kube-controller-manager.service                                      100%  429   331.5KB/s   00:00

[centos@k8s-master1 ~]$ scp -r /usr/lib/systemd/system/kube-scheduler.service root@192.168.0.22:/usr/lib/systemd/system
root@192.168.0.22's password:
kube-scheduler.service                                               100%  393   134.1KB/s   00:00

5)从第一个 Master 主控节点上退出登录:

[centos@k8s-master1 ~]$ exit
[centos@k8s-master2 ~]$

5、编辑 API Server 启动参数配置文件。

使用文本编辑器创建 "/usr/local/kubernetes/server/etc/kube-apiserver.conf" 文件:

[centos@k8s-master2 ~]$ sudo gedit /usr/local/kubernetes/server/etc/kube-apiserver.conf

编辑配置内容并保存:

KUBE_APISERVER_OPTS="...
--advertise-address=192.168.0.22 \
...

修改【--advertise-address】参数为当前节点的 IP 地址。

6、启动 API Server,Controller Manager,Scheduler 服务并设置开机自启动。

[centos@k8s-master2 ~]$ sudo systemctl daemon-reload
[centos@k8s-master2 ~]$ sudo systemctl start kube-apiserver.service
[centos@k8s-master2 ~]$ sudo systemctl start kube-controller-manager.service
[centos@k8s-master2 ~]$ sudo systemctl start kube-scheduler.service
[centos@k8s-master2 ~]$ sudo systemctl enable kube-apiserver.service
[centos@k8s-master2 ~]$ sudo systemctl enable kube-controller-manager.service
[centos@k8s-master2 ~]$ sudo systemctl enable kube-scheduler.service
[centos@k8s-master2 ~]$ sudo systemctl status kube-apiserver.service
[centos@k8s-master2 ~]$ sudo systemctl status kube-controller-manager.service
[centos@k8s-master2 ~]$ sudo systemctl status kube-scheduler.service

7、查看集群状态。

[centos@k8s-master2 ~]$ kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-1               Healthy   {"health":"true"}   
etcd-2               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"}   

所有其他 Master 主控节点全部需要按照以上步骤配置。


6.Master 高可用集群部署

Master 主控节点扮演着总控中心的角色,通过不断与工作节点上的 kubelet 和 kube-proxy 进行通信来维护整个集群的健康工作状态。如果 Master 节点故障,将无法使用 kubectl 工具或者 API 做任何集群管理。

Master 节点主要有三个服务 kube-apiserver、kube-controller-manager 和 kube-scheduler,其中 kubecontroller-manager 和 kube-scheduler 组件自身通过选择机制已经实现了高可用,所以 Master 高可用主要针对 kube-apiserver 组件,而该组件是以 HTTP API 提供服务,因此对他高可用与 Web 服务器类似,增加负载均衡器对其负载均衡即可,并且可水平扩容。

Nginx 是一个开源(遵循 BSD 协议)、高性能、高可靠的 Web 和反向代理服务器。主要用于 Web 应用的缓存和负载均衡,支持热部署、占用内存少、并发能力强,能支持高达 5w 个并发连接数。

Keepalived 是一个开源(遵循 GPLv2 协议)的、基于 VRRP 协议的轻量级服务高可用和负载均衡方案,提供避免服务器单点故障和请求分流的能力。它为 Nginx 扩展了高可用能力,共同组成完整的 Web 服务集群模式(高可用+负载均衡)。


6.1.Nginx 安装和配置

在各个 "Master 高可用节点" (k8s-proxy1、k8s-proxy1)安装、配置 Nginx,以 "k8s-proxy1" 为例:

1、打开 Nginx 下载页面【http://nginx.org/en/download.html】,下载 Nginx 的源代码 tar.gz 包到用户主目录中。

Nginx 下载页面

2、验证并安装依赖软件。通过源代码编译的方式安装 Nginx,需要依赖软件"make"、"gcc"、"pcre"、"pcre-devel"、"zlib"、"zlib-devel"、"openssl"、"openssl-devel",验证或安装依赖软件。

[centos@k8s-proxy1 ~]$ sudo dnf install make gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel

补充知识:

① "gcc"是一个C/C++、FORTRAN、JAVA、OBJC、ADA等多种语言的编译器,用来将源代码编译成可发布的软件程序。

② "make"是一个工程管理工具,能够根据 Makefile 中的脚本执行编译、安装流程。

③ "pcre"是一个正则表达式函数库;"pcre-devel"是它的开发库。

④ "zlib"是一个数据压缩函数库;"zib-devel"是它的开发库。

⑤ "openssl"是一个实现安全通信,避免窃听,同时确认另一端连接者身份的软件程序;"openssl-devel"是它的开发库。

3、解压缩 Nginx 的源代码 tar 包到用户主目录下。

[centos@k8s-proxy1 ~]$ tar -zxvf nginx-1.18.0.tar.gz
[centos@k8s-proxy1 ~]$ ll
drwxr-xr-x.  8 centos centos    4096 4月  21 22:09 nginx-1.18.0

4、安装 Nginx,进入源代码目录,配置、编译、安装程序。

[centos@k8s-proxy1 ~]$ cd nginx-1.18.0
[centos@k8s-proxy1 nginx-1.18.0]$ ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module  --with-stream
Configuration summary
  + using system PCRE library
  + OpenSSL library is not used
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

[centos@k8s-proxy1 nginx-1.18.0]$ make
[centos@k8s-proxy1 nginx-1.18.0]$ sudo make install

[centos@k8s-proxy1 ~]$ ll /usr/local/nginx
drwxr-xr-x. 2 root root 4096 5月  18 09:39 conf
drwxr-xr-x. 2 root root   40 5月  18 09:39 html
drwxr-xr-x. 2 root root    6 5月  18 09:39 logs
drwxr-xr-x. 2 root root   19 5月  18 09:39 sbin

程序安装目录是"/usr/local/nginx"。

5、设置 Nginx 配置文件参数。

使用文本编辑器打开配置文件:

[centos@k8s-proxy1 ~ ]$ sudo gedit /usr/local/nginx/conf/nginx.conf

在文件中追加的以下参数并保存:

# 四层负载均衡
stream {
    # 负载均衡
    upstream k8s-apiserver {
        server 192.168.0.21:6443 weight=1;
        server 192.168.0.22:6443 weight=1;
        server 192.168.0.23:6443 weight=1;
    }
    
    # 虚拟主机
    server {
        # 监听端口
        listen       6443;
        # 代理位置
        proxy_pass k8s-apiserver;
    }
}

6、配置 Nginx 开机自启动。

使用文本编辑器创建配置文件:

[centos@k8s-proxy1 ~ ]$ sudo gedit /usr/lib/systemd/system/nginx.service

编写文件内容并保存如下:

[Unit]
Description=Nginx
After=syslog.target network.target

[Service]
Type=forking
User=root
Group=root

ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

设置开机启动:

[centos@k8s-proxy1 ~ ]$ sudo systemctl daemon-reload
[centos@k8s-proxy1 ~ ]$ sudo systemctl enable nginx.service

7、启动 Nginx 服务。

[centos@k8s-proxy1 ~ ]$ sudo systemctl start nginx.service

8、设置防火墙端口(CentOS8默认安装firewall防火墙),允许"6443"端口(Nginx 默认端口)访问服务器。

[centos@k8s-proxy1 ~ ]$ sudo firewall-cmd --zone=public --add-port=6443/tcp --permanent
[centos@k8s-proxy1 ~ ]$ sudo firewall-cmd --reload

9、验证 Nginx 服务。使用浏览器访问 Web 代理服务。

注意:其他 "Master 高可用节点" 全部需要按照以上步骤配置。


6.2.Keepalived 安装和配置

在各个 "Master 高可用节点" (k8s-proxy1、k8s-proxy1)安装、配置 Keepalived,以 "高可用节点-1" 为例:

1、安装 EPEL 的 Yum源。

使用文本编辑器创建仓库配置文件:

[centos@k8s-proxy1 ~ ]$ sudo gedit /etc/yum.repos.d/epel.repo

在文件中编写以下内容并保存:

[epel-modular]
name=Extra Packages for Enterprise Linux Modular $releasever - $basearch
baseurl=http://mirrors.aliyun.com/epel/$releasever/Modular/$basearch
enabled=1
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-8

[epel]
name=Extra Packages for Enterprise Linux $releasever - $basearch
baseurl=http://mirrors.aliyun.com/epel/$releasever/Everything/$basearch
enabled=1
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-8

更新 Yum 源:

[centos@k8s-proxy1 ~]$ sudo dnf clean all
[centos@k8s-proxy1 ~]$ sudo dnf makecache
Extra Packages for Enterprise Linux Modular 8 - 429 kB/s | 118 kB     00:00    
Extra Packages for Enterprise Linux 8 - x86_64  3.7 MB/s | 6.9 MB     00:01    
元数据缓存已建立。

EPEL(Extra Packages for Enterprise Linux)是企业级 Linux 操作系统的扩展包仓库,为 Redhat/CentOS系统提供大量的额外软件包。

2、安装 Keepalived。

[centos@k8s-proxy1 ~]$ sudo dnf install keepalived

程序安装目录是"/usr/sbin",配置文件目录是"/etc/keepalived"。

3、设置 Keepalived 配置文件参数。

使用文本编辑器打开配置文件:

[centos@k8s-proxy1 ~ ]$ sudo gedit /etc/keepalived/keepalived.conf

在文件中编写以下内容并保存:

# 定义全局配置
global_defs {
    # 本地节点 ID 标识,一般设置为主机名。
    router_id k8s-proxy1
}

# 定义周期性执行的脚本,脚本的退出状态码会被调用它的所有的 vrrp_instance 记录。
vrrp_script chk_nginx {
    # 执行脚本的路径。
    script "/etc/keepalived/nginx_check.sh"
    # 脚本执行的间隔(单位是秒)。默认为1s。
    interval 2
    # 当脚本调整优先级,从 -254 到 254。默认为2。
    # 1. 如果脚本执行成功(退出状态码为0),weight大于0,则priority增加。
    # 2. 如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少。
    # 3. 其他情况下,priority不变。
    weight -20
    # 当脚本执行超过时长(单位是秒)则被认为执行失败。
    # 运行脚本的用户和组。
    user root root
    # timeout 30
    # 当脚本执行成功到设定次数时,才认为是成功。
    # rise 1
    # 当脚本执行失败到设定次数时,才认为是失败。
    # fall 3
}

# 定义虚拟路由,可以定义多个。
vrrp_instance VI_1 {
    # 本地节点初始状态,包括 MASTER(主节点) 和 BACKUP (备节点)。
    state MASTER
    # 本地节点绑定虚拟 IP 的网络接口。
    interface ens33
    # 本地节点优先级,优先级高的节点将动态变成 MASTER 节点,接管 VIP 。初始状态下,MASTER 节点的优先级必须高于 BACKUP 节点。
    priority 100
    # VRRP 实例 ID,范围是0-255。同一集群的所有节点应设置一致的值。
    virtual_router_id 216
    # 组播信息发送时间间隔。同一集群的所有节点必须设置一样,默认为1秒。
    advert_int 1
    # 设置验证信息。同一集群的所有节点必须一致
    authentication {
        # 指定认证方式。PASS 表示简单密码认证(推荐);AH:IPSEC认证(不推荐)。
        auth_type PASS
        # 指定认证所使用的密码,最多8位。
        auth_pass 1111
    }

    # 声明调用已定义的 vrrp_script 脚本。
    track_script {
        chk_nginx
    }

    # 定义虚拟 IP 地址。
    virtual_ipaddress {
        192.168.0.10
    }
}

初始化的主节点和备节点的区别体现在以下参数中:

  • 初始主节点
vrrp_instance VI_1 {
    # 必须设置为 MASTER 。
    state MASTER
    # 必须设置为最大值。
    priority 100
}
  • 初始备节点
vrrp_instance VI_1 {
    # 必须设置为 BACKUP 。
    state BACKUP
    # 必须设置为小于主节点的值。
    priority 90
}

4、创建或编辑 Nginx 检测脚本文件。文件路径对应配置文件中 vrrp_script 的 script 设置值。

使用文本编辑器创建脚本文件:

[centos@k8s-proxy1 ~ ]$ sudo gedit /etc/keepalived/nginx_check.sh

在脚本文件中编写以下内容并保存:

#!/bin/bash
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
    /usr/local/nginx/sbin/nginx
    sleep 2
    counter=$(ps -C nginx --no-heading|wc -l)
    if [ "${counter}" = "0" ]; then
        killall -9 keepalived
    fi
fi

给脚本文件增加可执行权限:

[centos@k8s-proxy1 ~ ]$ sudo chmod 755 /etc/keepalived/nginx_check.sh

5、配置 Keepalived 系统服务。

使用文本编辑器创建配置文件:

[centos@k8s-proxy1 ~ ]$ sudo gedit /usr/lib/systemd/system/keepalived.service

验证或修改文件内容并保存如下:

[Unit]
Description=LVS and VRRP High Availability Monitor
After=network-online.target syslog.target nginx.service
Wants=network-online.target
Requires=nginx.service

[Service]
Type=forking
User=root
Group=root
PIDFile=/var/run/keepalived.pid
KillMode=process
EnvironmentFile=-/etc/sysconfig/keepalived
ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

重新加载系统服务管理器:

[centos@k8s-proxy1 ~ ]$ sudo systemctl daemon-reload

6、设置防火墙端口(CentOS8默认安装firewall防火墙),允许"112"端口(Keepalived 默认端口)访问服务器。

[centos@k8s-proxy1 ~ ]$ sudo firewall-cmd --zone=public --add-port=112/tcp --permanent
[centos@k8s-proxy1 ~ ]$ sudo firewall-cmd --reload

7、启动/重启 Keepalived 服务(不建议设置为开机自启动)。

启动 Keepalived 服务之前,应确保已正确启动了各节点的 Nginx 服务。各节点的启动或重启的顺序为:① 启动 Keepalived 主节点;② 依次启动 Keepalived 备节点。

[centos@Proxy-1 ~ ]$ sudo systemctl restart keepalived.service

8、启动 Keepalived 可能因为各种未知的原因失败,主要是由于引发了 SELinux 异常。有关如何解决 SELinux 引起的异常,请阅读文章《RedHat/CentOS8【SELinux】引起的安全策略问题解决方案》,文章地址【https://www.jianshu.com/p/a13f974f8bae】。

注意:其他 "Master 高可用节点" 全部需要按照以上步骤配置。

9、验证 Nginx 高可用服务。使用浏览器通过虚拟 IP 访问代理服务。

有关 Nginx + Keepalived 实现 Web 应用高可用和负载均衡集群的内容,请阅读文章《应用架构之【Nginx+Keepalived】Web 集群方案》,文章地址【https://www.jianshu.com/p/185022cba563】。


7.Node 工作集群部署

以 "工作节点-1" 为例,所有 "Node 工作节点" 都需实施以下操作:

1、安装和配置 Docker 。

有关如何安装和配置 Docker,请阅读文章《RedHat/CentOS8【Docker】镜像制作编排和容器部署》的 “2.Docker 的安装和配置” 章节,文章地址【https://www.jianshu.com/p/a4198b127729】。

2、打开 K8s 下载页面【https://github.com/kubernetes/kubernetes/releases】,下载最新版本 Kubernetes Node 的编译程序 tar 包到用户主目录中。

第一步,点击链接进入编译程序下载页面
第二步,下载 Kubernetes Node 的 tar 包

3、解压缩编译程序 tar 包到"/usr/local"目录中,并管理工具创建系统 Shell 目录的软链接。

1)解压缩编译程序 tar 包到"/usr/local"目录中:

[centos@k8s-node1 ~]$ sudo tar zxvf kubernetes-node-linux-amd64.tar.gz -C /usr/local
[centos@k8s-node1 ~]$ ll /usr/local
drwxr-xr-x  3 root root  63 8月  14 00:49 kubernetes

安装目录:/usr/local/kubernetes/node
可执行程序目录:/usr/local/kubernetes/node/bin

2)为管理工具创建系统 Shell 目录的软链接:

[centos@k8s-node1 ~]$ sudo ln -s /usr/local/kubernetes/node/bin/kubectl /usr/bin/kubectl

4、创建 K8s Node 日志目录、秘钥目录、配置目录。

[centos@k8s-node1 ~]$ sudo mkdir -p /usr/local/kubernetes/node/{logs,ssl,etc}

5、从 SSL 证书服务器上获取已创建的 CA 根证书,Proxy 证书和 Proxy 证书秘钥 。

使用 ssh 远程登录到 SSL 证书服务器,并将 SSL 证书服务器上已制作好的 CA 根证书,Proxy 证书和 Proxy 证书秘钥通过 scp 拷贝到 "Node 工作节点"(当前主机) 的 K8s Node 秘钥目录中:

[centos@k8s-node1 ~]$ ssh centos@192.168.0.50
centos@192.168.0.50's password:
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/ca/ca.pem root@192.168.0.31:/usr/local/kubernetes/node/ssl
root@192.168.0.31's password:
ca.pem                                                                                     100% 1346   173.3KB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/proxy/proxy.pem root@192.168.0.31:/usr/local/kubernetes/node/ssl
root@192.168.0.31's password:
proxy.pem                                                                                  100% 1387   640.8KB/s   00:00
[centos@k8s-ssl ~]$ scp -r /data/ssl/k8s/proxy/proxy-key.pem root@192.168.0.31:/usr/local/kubernetes/node/ssl
root@192.168.0.31's password:
proxy-key.pem                                                                              100% 1679     2.1MB/s   00:00
[centos@k8s-ssl ~]$ exit

[centos@k8s-node1 ~]$ sudo chmod 644 /usr/local/kubernetes/node/ssl/*
[centos@k8s-node1 ~]$ ll /usr/local/kubernetes/node/ssl
-rw-r--r-- 1 root root 1346 8月  20 10:57 ca.pem
-rw-r--r-- 1 root root 1679 8月  20 11:00 proxy-key.pem
-rw-r--r-- 1 root root 1387 8月  20 10:58 proxy.pem

6、安装 CNI 网络插件。

1)打开 CNI 插件下载页面【https://github.com/containernetworking/plugins/releases】,下载最新版本 CNI 插件的编译程序 tar 包到用户主目录中:

CNI 插件下载页面

2)在 Node 工作节点的插件目录中创建 CNI 的程序目录和配置目录:

[centos@k8s-node1 ~]$ sudo mkdir -p /opt/cni/bin
[centos@k8s-node1 ~]$ sudo mkdir -p /etc/cni/net.d

3)解压缩编译程序 tar 包到"/opt/cni/bin"目录中:

[centos@k8s-node1 ~]$ sudo tar zxvf cni-plugins-linux-amd64-v0.8.7.tgz -C /opt/cni/bin

7、创建并编辑 Kubelet 的集群连接配置文件,采用 TLS Bootstrapping 动态证书。

1)生成集群连接信息:

[centos@k8s-node1 ~]$ sudo kubectl config set-cluster kube-cluster \
--certificate-authority=/usr/local/kubernetes/node/ssl/ca.pem  \
--embed-certs=true \
--server=https://192.168.0.10:6443 \
--kubeconfig=/usr/local/kubernetes/node/etc/bootstrap.kubeconfig

指令:kubectl config set-cluster <集群连接配置标识名> [参数...]
功能:设置 Kubelet 连接 K8s 集群的连接参数。

参数:

  • --server:连接的 Master 集群 Keepalived Virtual IP(高可用集群的虚拟 IP 地址)的 API Server 的地址和端口号。
  • --certificate-authority:用以进行认证授权的证书文件路径。
  • --embed-certs:是否在配置文件中嵌入证书。
  • --kubeconfig:配置文件位置。

2)生成用户认证信息:

[centos@k8s-node1 ~]$ sudo kubectl config set-credentials kube-users \
--token="d682ded2c1468b8c6a16375b48a638ff" \
--kubeconfig=/usr/local/kubernetes/node/etc/bootstrap.kubeconfig

指令:kubectl config set-credentials <用户认证配置标识名> [参数...]
功能:设置 Kubelet 连接 K8s 集群的用户认证参数。

参数:

  • --token:在 Master 集群或节点上定义的 TLS Bootstrapping 的 Token 配置文件中的 Token 值。详见 “1.5.Master 主控节点部署” 章节第5步 “启用 TLS Bootstrapping 机制” 的相关内容。
  • --kubeconfig:配置文件位置。

3)生成配置文件的上下文信息:

[centos@k8s-node1 ~]$ sudo kubectl config set-context kube-context \
--cluster=kube-cluster \
--user=kube-users \
--kubeconfig=/usr/local/kubernetes/node/etc/bootstrap.kubeconfig

指令:kubectl config set-context <上下文配置标识名> [参数...]
功能:设置 Kubelet 配置的上下文信息。

参数:

  • --cluster:配置文件中的 "cluster" 节点的 "name" 属性(集群连接配置标识名)值。
  • --user:配置文件中的 "users" 节点的 "name" 属性(用户认证配置标识名)值。
  • --kubeconfig:配置文件位置。

4)生成配置文件的当前上下文:

[centos@k8s-node1 ~]$ sudo kubectl config use-context kube-context  \
--kubeconfig=/usr/local/kubernetes/node/etc/bootstrap.kubeconfig

指令:kubectl config use-context <上下文配置标识名> [参数...]
功能:设置 Kubelet 配置的当前上下文。

参数:

  • --kubeconfig:配置文件位置。

5)查看已生成的文件:

[centos@k8s-node1 ~]$ sudo cat /usr/local/kubernetes/node/etc/bootstrap.kubeconfig

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0RENDQXB5Z0F3SUJBZ0lVRkd1Q1luWC9FZEd...
    server: https://192.168.0.10:6443
  name: kube-cluster
contexts:
- context:
    cluster: kube-cluster
    user: kube-users
  name: kube-context
current-context: kube-context
kind: Config
preferences: {}
users:
- name: kube-users
  user:
    token: d682ded2c1468b8c6a16375b48a638ff

8、创建并编辑 Kubelet 核心配置文件。

[centos@k8s-node1 ~]$  sudo gedit /usr/local/kubernetes/node/etc/kubelet-config.yml

编写文件内容并保存如下(删除注释):

kind: KubeletConfiguration
# API 版本。
apiVersion: kubelet.config.k8s.io/v1beta1
# 监听地址。
address: 0.0.0.0
# 监听端口。
port: 10250
# 读取监听端口,一般用不上,可以不设置或保持默认设置。
readOnlyPort: 10255
# Docker 驱动,与 Docker 的【Cgroup Driver】属性一致,Docker 的 【Cgroup Driver】属性可以通过指令 "docker info" 查看。
cgroupDriver: cgroupfs
# 服务的 DNS 服务地址。
clusterDNS:
  - 10.0.0.2
# kubelet 集群的域名。
clusterDomain: cluster.local 
# 是否启动虚拟内存。
failSwapOn: false
# 认证授权配置
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    # 客户端 CA 证书文件位置
    clientCAFile: /usr/local/kubernetes/node/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
# 最大 Pod 数量。
maxPods: 110

9、创建并编辑 Kebelet 启动参数配置文件。

使用文本编辑器创建 "/usr/local/kubernetes/node/etc/kubelet.conf" 文件:

[centos@k8s-node1 ~]$ sudo gedit /usr/local/kubernetes/node/etc/kubelet.conf

编辑配置内容并保存:

KUBELET_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/usr/local/kubernetes/node/logs \
--hostname-override=k8s-node1 \
--network-plugin=cni \
--cni-conf-dir=/etc/cni/net.d \
--cni-bin-dir=/opt/cni/bin \
--kubeconfig=/usr/local/kubernetes/node/etc/kubelet.kubeconfig \
--bootstrap-kubeconfig=/usr/local/kubernetes/node/etc/bootstrap.kubeconfig \
--config=/usr/local/kubernetes/node/etc/kubelet-config.yml \
--cert-dir=/usr/local/kubernetes/node/ssl \
--pod-infra-container-image=quay.io/coreos/flannel:v0.12.0-amd64"

参数说明:

  • --logtostderr:是否启用日志。
  • --v:日志记录等级,可选范围【0-8】,数值越大日志越详细。
  • --log-dir:日志文件存储目录。
  • --hostname-override:Node 节点名称,在集群中是唯一的。
  • --network-plugin:网络插件,一般指定为 "cni" 表示启用 CNI 网络。
  • --cni-conf-dir:CNI 插件的配置文件目录,默认为 "/etc/cni/net.d"。
  • --cni-bin-dir:CNI插件的可执行文件目录,默认为 "/opt/cni/bin"。
  • --kubeconfig: 空路径,会自动生成,用于连接 API Server。
  • --bootstrap-kubeconfig: Kubelet 的 TLS Bootstrapping 动态证书配置文件位置。
  • --config:Kubelet 核心配置文件位置。
  • --cert-dir:Kubelet 证书生成目录。
  • --pod-infra-container-image:管理 CNI 网络容器的镜像名称和版本。指定的镜像和版本应该跟 CNI 插件的 Flannel 镜像名字和版本保持一致。

10、配置 Kebelet 启动服务。

使用文本编辑器创建配置文件:

[centos@k8s-node1 ~]$ sudo gedit /usr/lib/systemd/system/kubelet.service

编写文件内容并保存如下:

[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service

[Service]
User=root
Group=root
EnvironmentFile=/usr/local/kubernetes/node/etc/kubelet.conf
ExecStart=/usr/local/kubernetes/node/bin/kubelet $KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

11、启动 Kebelet 服务并设置开机自启动。

[centos@k8s-node1 ~]$ sudo systemctl daemon-reload
[centos@k8s-node1 ~]$ sudo systemctl start kubelet.service
[centos@k8s-node1 ~]$ sudo systemctl enable kubelet.service
[centos@k8s-node1 ~]$ sudo systemctl status kubelet.service

12、创建并编辑 Proxy 的集群连接配置文件。

1)生成集群连接信息:

[centos@k8s-node1 ~]$ sudo kubectl config set-cluster kube-cluster \
--certificate-authority=/usr/local/kubernetes/node/ssl/ca.pem  \
--embed-certs=true \
--server=https://192.168.0.10:6443 \
--kubeconfig=/usr/local/kubernetes/node/etc/kube-proxy.kubeconfig

指令:kubectl config set-cluster <集群连接配置标识名> [参数...]
功能:设置 Kubelet 连接 K8s 集群的连接参数。

参数:

  • --server:连接的 Master 集群 Keepalived Virtual IP(高可用集群的虚拟 IP 地址)的 API Server 的地址和端口号。
  • --certificate-authority:用以进行认证授权的证书文件路径。
  • --embed-certs:是否在配置文件中嵌入证书。
  • --kubeconfig:配置文件位置。

2)生成用户认证信息:

[centos@k8s-node1 ~]$ sudo kubectl config set-credentials kube-users \
--client-certificate=/usr/local/kubernetes/node/ssl/proxy.pem \
--client-key=/usr/local/kubernetes/node/ssl/proxy-key.pem \
--embed-certs=true \
--kubeconfig=/usr/local/kubernetes/node/etc/kube-proxy.kubeconfig

指令:kubectl config set-credentials <用户认证配置标识名> [参数...]
功能:设置 Kubelet 连接 K8s 集群的用户认证参数。

参数:

  • --client-certificate:用于连接 Master 集群或节点的 API Server 使用的证书文件。
  • --client-key:用于连接 Master 集群或节点的 API Server 使用的证书秘钥文件。
  • --embed-certs:是否在配置文件中嵌入证书。
  • --kubeconfig:配置文件位置。

3)生成配置文件的上下文信息:

[centos@k8s-node1 ~]$ sudo kubectl config set-context kube-context \
--cluster=kube-cluster \
--user=kube-users \
--kubeconfig=/usr/local/kubernetes/node/etc/kube-proxy.kubeconfig

指令:kubectl config set-context <上下文配置标识名> [参数...]
功能:设置 Kubelet 配置的上下文信息。

参数:

  • --cluster:配置文件中的 "cluster" 节点的 "name" 属性(集群连接配置标识名)值。
  • --user:配置文件中的 "users" 节点的 "name" 属性(用户认证配置标识名)值。
  • --kubeconfig:配置文件位置。

4)生成配置文件的当前上下文:

[centos@k8s-node1 ~]$ sudo kubectl config use-context kube-context  \
--kubeconfig=/usr/local/kubernetes/node/etc/kube-proxy.kubeconfig

指令:kubectl config use-context <上下文配置标识名> [参数...]
功能:设置 Kubelet 配置的当前上下文。

参数:

  • --kubeconfig:配置文件位置。

5)查看已生成的文件:

[centos@k8s-node1 ~]$ sudo cat /usr/local/kubernetes/node/etc/kube-proxy.kubeconfig

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0RENDQXB5Z0F3SUJBZ0lVRkd1Q1luWC9FZEd...
    server: https://192.168.0.10:6443
  name: kube-cluster
contexts:
- context:
    cluster: kube-cluster
    user: kube-users
  name: kube-context
current-context: kube-context
kind: Config
preferences: {}
users:
- name: kube-users
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQwekNDQXJ1Z0F3SUJBZ0lVVE1odys4MHBsc21...
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdWN1aXB6d01WbW...

13、创建并编辑 Proxy 核心配置文件。

使用文本编辑器创建 "/usr/local/kubernetes/node/etc/kube-proxy-config.yml" 文件:

[centos@k8s-node1 ~]$ sudo gedit /usr/local/kubernetes/node/etc/kube-proxy-config.yml

编辑配置内容并保存:

kind: KubeProxyConfiguration
# API 版本。
apiVersion: kubeproxy.config.k8s.io/v1alpha1
# Node 节点名称,在集群中是唯一的。
hostnameOverride: k8s-node1
# 监听地址。
bindAddress: 0.0.0.0
# 指标暴露地址和端口,用于监控系统使用,使用默认配置即可。
metricsBindAddress: 0.0.0.0:10249
# Pod 的 CNI 网络地址段。
clusterCIDR: 10.254.0.0/16
# 集群连接配置文件位置
clientConnection:
  kubeconfig: /usr/local/kubernetes/node/etc/kube-proxy.kubeconfig

14、创建并编辑 Proxy 启动参数配置文件。

使用文本编辑器创建 "/usr/local/kubernetes/node/etc/kube-proxy.conf" 文件:

[centos@k8s-node1 ~]$ sudo gedit /usr/local/kubernetes/node/etc/kube-proxy.conf

编辑配置内容并保存:

KUBE_PROXY_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/usr/local/kubernetes/node/logs \
--config=/usr/local/kubernetes/node/etc/kube-proxy-config.yml"

参数说明:

  • --logtostderr:是否启用日志。
  • --v:日志记录等级,可选范围【0-8】,数值越大日志越详细。
  • --log-dir:日志文件存储目录。
  • --config:Proxy 核心配置文件位置。

15、配置 Proxy 启动服务。

使用文本编辑器创建配置文件:

[centos@k8s-node1 ~]$ sudo gedit /usr/lib/systemd/system/kube-proxy.service

编写文件内容并保存如下:

[Unit]
Description=Kubernetes Proxy
After=network.target

[Service]
User=root
Group=root
EnvironmentFile=/usr/local/kubernetes/node/etc/kube-proxy.conf
ExecStart=/usr/local/kubernetes/node/bin/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

16、启动 Proxy 服务并设置开机自启动。

[centos@k8s-node1 ~]$ sudo systemctl daemon-reload
[centos@k8s-node1 ~]$ sudo systemctl start kube-proxy.service
[centos@k8s-node1 ~]$ sudo systemctl enable kube-proxy.service
[centos@k8s-node1 ~]$ sudo systemctl status kube-proxy.service

注意:其他"Node 工作节点"上全部需要按照以上步骤配置。

17、在集群启用 TLS Bootstrapping 机制时,当 Kubelet 启动后,会自动向 Master 节点发起证书申请,当 Master 节点批准申请后,Node 节点才能加入到集群中。因此,当有新的 Node 工作节点部署完成并启动 Kubelet 后,需要在 Master 节点上批准该 Node 节点的证书申请。

注意:以下操作在 Node 工作节点的 Kubelet 正常启动后,到 Master 主控节点上执行:

1)查看 Node 工作节点发起的证书申请:

[centos@k8s-master1 ~]$ kubectl get csr
NAME                                                   AGE    SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-w-cAh8lsq4EFbT8IVFHIX1DtrncqzwTKYOqV9R4Hwus   101m   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending
node-csr-z0cIayC5dTJwl38XU2wsB3oQOLocpaSNd9Svg21mceQ   106m   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending

说明:
【NAME】表示“申请名称”。
【CONDITION】表示“处理步骤”。"Pending" 表示 “待申请”;"Pending,Issued" 表示 “待申请,已批准”。

2)批准 Node 工作节点发起的证书申请:

[centos@k8s-master1 ~]$ kubectl certificate approve node-csr-w-cAh8lsq4EFbT8IVFHIX1DtrncqzwTKYOqV9R4Hwus

certificatesigningrequest.certificates.k8s.io/node-csr-w-cAh8lsq4EFbT8IVFHIX1DtrncqzwTKYOqV9R4Hwus approved

[centos@k8s-master1 ~]$ kubectl certificate approve node-csr-z0cIayC5dTJwl38XU2wsB3oQOLocpaSNd9Svg21mceQ

certificatesigningrequest.certificates.k8s.io/node-csr-z0cIayC5dTJwl38XU2wsB3oQOLocpaSNd9Svg21mceQ approved

命令格式:kubectl certificate approve <申请名称>

3)查看 Node 工作节点发起的证书申请结果:

[centos@k8s-master1 ~]$ kubectl get csr
NAME                                                   AGE    SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-w-cAh8lsq4EFbT8IVFHIX1DtrncqzwTKYOqV9R4Hwus   106m   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Approved,Issued
node-csr-z0cIayC5dTJwl38XU2wsB3oQOLocpaSNd9Svg21mceQ   111m   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Approved,Issued

4)查看 Node 工作节点的状态:

[centos@k8s-master1 ~]$ kubectl get node
NAME        STATUS     ROLES    AGE     VERSION
k8s-node1   NotReady   <none>   5m55s   v1.18.8
k8s-node2   NotReady   <none>   6m31s   v1.18.8

注意
证书申请审批通过后,可以在 Master 主控节点上查看各 Node 工作节点的状态。【STATUS】为“NotReady”,表示 Node 工作节点是“没有准备就绪”状态,这是因为还没有配置集群 CNI 网络,在 CNI 网络配置完成后,Node 工作节点才能准备就绪。


8.CNI 容器网络(Flannel 插件)部署

在 Master 主控集群的任意一个节点部署一次 Flannel 插件即可。

有关如何安装和配置 Flannel 插件,请阅读文章《云架构之【Kubernetes(K8s)】第二部分:单主控集群部署》的 “7.CNI 容器网络(Flannel 插件)部署” 章节,文章地址【https://www.jianshu.com/p/8824575f2fe0】。


9.DNS 域名发现(CoreDNS 插件)部署

在 Master 主控集群的任意一个节点部署一次 CoreDNS 插件即可。

有关如何安装和配置 Flannel 插件,请阅读文章《云架构之【Kubernetes(K8s)】第二部分:单主控集群部署》的 “8.DNS 域名发现(CoreDNS 插件)部署” 章节,文章地址【https://www.jianshu.com/p/8824575f2fe0】。


10.用户管理界面(Dashboard 插件)部署

在 Master 主控集群的任意一个节点部署一次 Dashboard 插件即可。

有关如何安装和配置 Flannel 插件,请阅读文章《云架构之【Kubernetes(K8s)】第二部分:单主控集群部署》的 “9.用户管理界面(Dashboard 插件)部署” 章节,文章地址【https://www.jianshu.com/p/8824575f2fe0】。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345