k8s二进制部署(一)---单节点部署

目录

一、环境准备

二、部署etcd集群

1、下载证书

2、编写 etcd-cert.sh 和 etcd.sh 脚本

3、生成 CA 证书、etcd 服务器证书以及私钥

4、安装 etcd 服务

 5、创建用于存放 etcd 配置文件、命令文件、证书的目录

6、启动etcd.sh 脚本 

7、把 etcd 相关证书文件和命令文件全部拷贝到另外两个 etcd 集群节点

8、把 etcd 服务管理文件拷贝到了另外两个 etcd 集群节点

9、修改另外两个 etcd 集群节点的配置文件

10、 检查集群状态(master01)

三、部署 docker 引擎(所有 node 节点)

四、flannel 网络配置 

1、K8S 中 Pod 网络通信

2、Overlay Network

3、 VXLAN

4、Flannel 简介

5、Flannel 工作原理

6、ETCD 之 Flannel 功能说明

7、Flannel 部署

7.1  在 master01 节点上操

7.2  在所有 node 节点上操作

7.3  修改 docker0 网卡网段与 flannel 一致 

7.4  容器间跨网通信 

五、部署 master 组件(master01 节点)

1、编写 apiserver.sh、scheduler.sh、controller-manager.sh

1.1  编写 apiserver.sh

1.2  编写 scheduler.sh 

1.3  编写 controller-manager.sh

2、编写 k8s-cert.sh 

3、创建 kubernetes 工作目录

4、生成 CA 证书、相关组件的证书和私钥

5、复制 CA 证书、apiserver 相关证书和私钥到 kubernetes 工作目录的 ssl 子目录中

6、下载或上传 kubernetes 安装包到 /k8s 目录,并解压

7、复制 master 组件的关键命令文件到 kubernetes 工作目录的 bin 子目录中

 8、创建 bootstrap token 认证文件

9、二进制文件、token、证书都准备好后,开启 apiserver 服务

10、检查

10.1  检查进程是否启动成功

10.2  检查 6443 端口

10.3  检查 8080 端口

10.4  查看版本信息

11 、启动 scheduler 服务

12、启动 controller-manager 服务

13、查看 master 节点状态

六、 部署 Worker Node 组件

1、把 kubelet、kube-proxy 拷贝到 node 节点(master01 节点)

2、编写脚本(node01 节点)

2.1  编写proxy.sh

2.2  编写 kubelet.sh

2.3  赋予上述脚本执行权限

3、在 master01 节点上操作

3.1  创建用于生成 kubelet 的配置文件的目录

3.2  编写 kubeconfig.sh

3.3  生成 kubelet 的配置文件

3.4  把配置文件 bootstrap.kubeconfig、kube-proxy.kubeconfig 拷贝到 node 节点

3.5  RBAC 授权及相关说明

3.6  查看角色

3.7   查看已授权的角色

4、在 node1 节点上操作

4.1  使用 kubelet.sh 脚本启动 kubelet 服务

4.2  检查 kubelet 服务启动

4.3  查看当前 ssl 目录

5、在 master01 节点上操作

5.1  查看 CSR 请求

5.2  通过 CSR 请求

5.3  再次查看 CSR 请求状态

5.4  查看集群节点状态

6、在 node01 节点上操作

6.1  已自动生成证书和 kubelet.kubeconfig 文件

6.2  加载 ip_vs 模块

6.3  使用 proxy.sh 脚本启动 proxy 服务

7、node02 节点部署

7.1   在 node01 节点操作

7.2  在 node02 节点上操作

7.3  在 master01 节点上操作

7.4  node02 操作

8、K8S 单节点测试


一、环境准备

服务器主机名IP地址主要组件
k8s集群master01 + etcd01master01192.168.61.17kube-apiserver kube-controller-manager kube-schedular etcd
k8s集群node01 + etcd02node01192.168.61.18kubelet kube-proxy docker flannel
k8s集群node02 + etcd03node02192.168.61.22kubelet kube-proxy docker flannel
#关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
setenforce 0

#修改主机名
hostnamectl set-hostname master01
hostnamectl set-hostname node01
hostnamectl set-hostname node02

#关闭swap(所有节点)
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

#添加 hosts(所有节点)
cat >> /etc/hosts << EOF
192.168.3.11 master01
192.168.3.12 node01
192.168.3.13 node02
EOF

#将桥接的 IPv4 流量传递到 iptables 的链(所有节点)
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

#时间同步(所有节点)
yum install ntpdate -y
ntpdate time.windows.com

二、部署etcd集群

1、下载证书

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


//cfssl:证书签发的工具命令
//cfssljson:将 cfssl 生成的证书(json 格式)变为文件承载式证书
//cfssl-certinfo:验证证书的信息
//“cfssl-certinfo -cert <证书名称>” 可查看证书的信息

2、编写 etcd-cert.sh 和 etcd.sh 脚本

[root@master1 ~]# mkdir /k8s
[root@master1 ~]# cd /k8s
[root@master k8s]# vim etcd-cert.sh		//注意修改称自己的IP
#!/bin/bash
#配置证书生成策略,让 CA 软件知道颁发有什么功能的证书,生成用来签发其他组件证书的根证书
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "www": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF
 
#ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;
#后续在签名证书时会使用某个 profile;此实例只有一个 www 模板。
#expiry:指定了证书的有效期,87600h 为10年,如果用默认值一年的话,证书到期后集群会立即宕掉
#signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
#key encipherment:表示使用非对称密钥加密,如 RSA 加密;
#server auth:表示client可以用该 CA 对 server 提供的证书进行验证;
#client auth:表示server可以用该 CA 对 client 提供的证书进行验证;
#注意标点符号,最后一个字段一般是没有逗号的。
 
 
#-----------------------
#生成CA证书和私钥(根证书和私钥)
#特别说明: cfssl和openssl有一些区别,openssl需要先生成私钥,然后用私钥生成请求文件,最后生成签名的证书和私钥等,但是cfssl可以直接得到请求文件。
cat > ca-csr.json <<EOF
{
    "CN": "etcd",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]
}
EOF
 
#CN:Common Name,浏览器使用该字段验证网站或机构是否合法,一般写的是域名 
#key:指定了加密算法,一般使用rsa(size:2048)
#C:Country,国家
#ST:State,州,省
#L:Locality,地区,城市
#O: Organization Name,组织名称,公司名称
#OU: Organization Unit Name,组织单位名称,公司部门
 
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
 
#生成的文件:
#ca-key.pem:根证书私钥
#ca.pem:根证书
#ca.csr:根证书签发请求文件
 
#cfssl gencert -initca <CSRJSON>:使用 CSRJSON 文件生成生成新的证书和私钥。如果不添加管道符号,会直接把所有证书内容输出到屏幕。
#注意:CSRJSON 文件用的是相对路径,所以 cfssl 的时候需要 csr 文件的路径下执行,也可以指定为绝对路径。
#cfssljson 将 cfssl 生成的证书(json格式)变为文件承载式证书,-bare 用于命名生成的证书文件。
 
 
#-----------------------
#生成 etcd 服务器证书和私钥
cat > server-csr.json <<EOF
{
    "CN": "etcd",
    "hosts": [
    "192.168.3.11",
    "192.168.3.12",
    "192.168.3.13"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing"
        }
    ]
}
EOF
 
#hosts:将所有 etcd 集群节点添加到 host 列表,需要指定所有 etcd 集群的节点 ip 或主机名不能使用网段,新增 etcd 服务器需要重新签发证书。
 
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
 
#生成的文件:
#server.csr:服务器的证书请求文件
#server-key.pem:服务器的私钥
#server.pem:服务器的数字签名证书
 
#-config:引用证书生成策略文件 ca-config.json
#-profile:指定证书生成策略文件中的的使用场景,比如 ca-config.json 中的 www
>>>>wq

----------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------
[root@master k8s]# vim etcd.sh		//注意修改称自己的IP
#!/bin/bash
# example: ./etcd.sh etcd01 192.168.3.11 etcd02=https://192.168.3.12:2380,etcd03=https://192.168.3.13:2380
 
#创建etcd配置文件/opt/etcd/cfg/etcd
ETCD_NAME=$1
ETCD_IP=$2
ETCD_CLUSTER=$3
 
WORK_DIR=/opt/etcd
 
cat > $WORK_DIR/cfg/etcd  <<EOF
#[Member]
ETCD_NAME="${ETCD_NAME}"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_LISTEN_CLIENT_URLS="https://${ETCD_IP}:2379"
 
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://${ETCD_IP}:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://${ETCD_IP}:2380,${ETCD_CLUSTER}"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
 
#Member:成员配置
#ETCD_NAME:节点名称,集群中唯一。成员名字,集群中必须具备唯一性,如etcd01
#ETCD_DATA_DIR:数据目录。指定节点的数据存储目录,这些数据包括节点ID,集群ID,集群初始化配置,Snapshot文件,若未指定-wal-dir,还会存储WAL文件;如果不指定会用缺省目录
#ETCD_LISTEN_PEER_URLS:集群通信监听地址。用于监听其他member发送信息的地址。ip为全0代表监听本机所有接口
#ETCD_LISTEN_CLIENT_URLS:客户端访问监听地址。用于监听etcd客户发送信息的地址。ip为全0代表监听本机所有接口
 
#Clustering:集群配置
#ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址。其他member使用,其他member通过该地址与本member交互信息。一定要保证从其他member能可访问该地址。静态配置方式下,该参数的value一定要同时在--initial-cluster参数中存在
#ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址。etcd客户端使用,客户端通过该地址与本member交互信息。一定要保证从客户侧能可访问该地址
#ETCD_INITIAL_CLUSTER:集群节点地址。本member使用。描述集群中所有节点的信息,本member根据此信息去联系其他member
#ETCD_INITIAL_CLUSTER_TOKEN:集群Token。用于区分不同集群。本地如有多个集群要设为不同
#ETCD_INITIAL_CLUSTER_STATE:加入集群的当前状态,new是新集群,existing表示加入已有集群。
 
 
#创建etcd.service服务管理文件
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=${WORK_DIR}/cfg/etcd
ExecStart=${WORK_DIR}/bin/etcd \
--name=\${ETCD_NAME} \
--data-dir=\${ETCD_DATA_DIR} \
--listen-peer-urls=\${ETCD_LISTEN_PEER_URLS} \
--listen-client-urls=\${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379 \
--advertise-client-urls=\${ETCD_ADVERTISE_CLIENT_URLS} \
--initial-advertise-peer-urls=\${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
--initial-cluster=\${ETCD_INITIAL_CLUSTER} \
--initial-cluster-token=\${ETCD_INITIAL_CLUSTER_TOKEN} \
--initial-cluster-state=new \
--cert-file=${WORK_DIR}/ssl/server.pem \
--key-file=${WORK_DIR}/ssl/server-key.pem \
--trusted-ca-file=${WORK_DIR}/ssl/ca.pem \
--peer-cert-file=${WORK_DIR}/ssl/server.pem \
--peer-key-file=${WORK_DIR}/ssl/server-key.pem \
--peer-trusted-ca-file=${WORK_DIR}/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target
EOF
 
#--listen-client-urls:用于指定etcd和客户端的连接端口
#--advertise-client-urls:用于指定etcd服务器之间通讯的端口,etcd有要求,如果--listen-client-urls被设置了,那么就必须同时设置--advertise-client-urls,所以即使设置和默认相同,也必须显式设置
#--peer开头的配置项用于指定集群内部TLS相关证书(peer 证书),这里全部都使用同一套证书认证
#不带--peer开头的的参数是指定 etcd 服务器TLS相关证书(server 证书),这里全部都使用同一套证书认证
 
 
systemctl daemon-reload
systemctl enable etcd
systemctl restart etcd
>>>>>wq

[root@master k8s]# chmod +x etcd-cert.sh
[root@master k8s]# chmod +x etcd.sh

3、生成 CA 证书、etcd 服务器证书以及私钥

[root@master k8s]# mkdir /k8s/etcd-cert
[root@master k8s]# mv etcd-cert.sh etcd-cert/
[root@master k8s]# cd etcd-cert/
[root@master etcd-cert]# ./etcd-cert.sh
#生成CA证书、etcd服务器证书以及私钥
[root@master etcd-cert]# ls
ca-config.json  ca-csr.json  ca.pem        server.csr       server-key.pem
ca.csr          ca-key.pem   etcd-cert.sh  server-csr.json  server.pem

4、安装 etcd 服务

etcd 二进制包地址:https://github.com/etcd-io/etcd/releases

[root@master etcd-cert]# cd /k8s/
[root@master k8s]# rz -E
#传入etcd安装包etcd-v3.3.10-linux-amd64.tar.gz

[root@master k8s]# tar zxvf etcd-v3.3.10-linux-amd64.tar.gz
[root@master01 k8s]# ls etcd-v3.3.10-linux-amd64
Documentation  etcd  etcdctl  README-etcdctl.md  README.md  READMEv2-etcdctl.md

//etcd 就是 etcd 服务的启动命令,后面可跟各种启动参数
//etcdctl 主要为 etcd 服务提供了命令行操作

 5、创建用于存放 etcd 配置文件、命令文件、证书的目录

[root@master01 k8s]# mkdir -p /opt/etcd/{cfg,bin,ssl}
[root@master01 k8s]# mv /k8s/etcd-v3.3.10-linux-amd64/etcd /k8s/etcd-v3.3.10-linux-amd64/etcdctl /opt/etcd/bin/
[root@master01 bin]# cp /k8s/etcd-cert/*.pem /opt/etcd/ssl/

6、启动etcd.sh 脚本 

./etcd.sh etcd01 192.168.61.17 etcd02=https://192.168.61.18:2380,etcd03=https://192.168.61.22:2380

//进入卡住状态等待其他节点加入,这里需要三台 etcd 服务同时启动,如果只启动其中一台后,服务会卡在那里,直到集群中所有 etcd 节点都已启动
  • 另外打开一个窗口查看 etcd 进程是否正常
[root@master01 ~]# ps -ef | grep etcd
root       2632   2169  0 15:32 pts/1    00:00:00 /bin/bash ./etcd.sh etcd01 192.168.61.17 etcd02=https://192.168.61.18:2380,etcd03=https://192.168.61.22:2380
root       2683   2632  0 15:32 pts/1    00:00:00 systemctl restart etcd
root       2691      1  5 15:32 ?        00:00:03 /opt/etcd/bin/etcd --name=etcd01 --data-dir=/var/lib/etcd/default.etcd --listen-peer-urls=https://192.168.61.17:2380 --listen-client-urls=https://192.168.61.17:2
379,http://127.0.0.1:2379 --advertise-client-urls=https://192.168.61.17:72379 --initial-advertise-peer-urls=https://192.168.61.17:2380 --initial-cluster=etcd01=https://192.168.61.17:2380,etcd02=https://192.168.61.18:2380,etcd03=https://192.168.61.22:2380 --initial-cluster-token=etcd-cluster --initial-cluster-state=new --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --trusted-ca-file=/opt/etc/ssl/ca.pem --peer-cert-file=/opt/etcd/ssl/server.pem --peer-key-file=/opt/etcd/ssl/server-key.pem --peer-trusted-ca-file=/opt/etcd/ssl/ca.pemroot       2774   2719  0 15:34 pts/2    00:00:00 grep --color=auto etcd

7、把 etcd 相关证书文件和命令文件全部拷贝到另外两个 etcd 集群节点

scp -r /opt/etcd/ root@192.168.61.18:/opt/etcd/
scp -r /opt/etcd/ root@192.168.61.22:/opt/etcd/

8、把 etcd 服务管理文件拷贝到了另外两个 etcd 集群节点

[root@master01 ~]# scp /usr/lib/systemd/system/etcd.service root@192.168.61.18:/usr/lib/systemd/system/
......
[root@master01 ~]# scp /usr/lib/systemd/system/etcd.service root@192.168.61.22:/usr/lib/systemd/system/
......      

9、修改另外两个 etcd 集群节点的配置文件

node1 和 node2 操作相同,注意修改节点名和 IP

[root@node01 ~]# cd /opt/etcd/cfg/
[root@node01 cfg]# ls
etcd
[root@node01 cfg]# vim etcd
 
#[Member]
ETCD_NAME="etcd01"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.61.18:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.61.18:2379"

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.61.18:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.61.17:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.61.17:2380,etcd02=https://192.168.61.18:2380,etcd03
=https://192.168.61.22:2380"ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

>>>>wq

[root@node01 cfg]# systemctl daemon-reload 
[root@node01 cfg]# systemctl enable --now etcd.service 
[root@node01 cfg]# systemctl status etcd | grep Active
   Active: active (running) since 三 2021-12-15 15:41:59 CST; 5min ago

10、 检查集群状态(master01)

v2版本查看(默认版本)

[root@master01 k8s]# ln -s /opt/etcd/bin/etcd* /usr/local/bin
#将etcd执行命令软链接到PATH路径
[root@master01 k8s]# cd /opt/etcd/ssl
[root@master01 ssl]# etcdctl --ca-file=ca.pem --cert-file=server.pem --key-file=server-key.pem --endpoints="https://192.168.10.100:2379,https://192.168.10.101:2379,https://192.168.10.102:2379" cluster-health
member 9302ad482744beb is healthy: got healthy result from https://192.168.61.22:2379
member 8f0b2f8f5a943bdf is healthy: got healthy result from https://192.168.61.18:2379
member f330bec74ce6cc42 is healthy: got healthy result from https://192.168.61.17:2379
cluster is healthy

--------------------------
etcdctl \
--ca-file=ca.pem \
--cert-file=server.pem \
--key-file=server-key.pem \
--endpoints="https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.61.22:2379" \
cluster-health

v3 版本查看

切换到 etcd3 版本查看集群节点状态和成员列表
v2 和 v3 命令略有不同,etcd2 和 etcd3 也是不兼容的,默认版本是 v2 版本 

[root@master01 ssl]# export ETCDCTL_API=3
[root@master01 ssl]# etcdctl --write-out=table endpoint status
+----------------+------------------+---------+---------+-----------+-----------+------------+
|    ENDPOINT    |        ID        | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+----------------+------------------+---------+---------+-----------+-----------+------------+
| 127.0.0.1:2379 | 71f26872cb1756fc |  3.3.10 |   20 kB |     false |       377 |         14 |
+----------------+------------------+---------+---------+-----------+-----------+------------+
[root@master01 ssl]# etcdctl --write-out=table member list
+------------------+---------+--------+---------------------------+---------------------------
+|        ID        | STATUS  |  NAME  |        PEER ADDRS         |       CLIENT ADDRS        
|+------------------+---------+--------+---------------------------+---------------------------
+| 1e3ccef658341896 | started | etcd02 | https://192.168.61.18:2380 | https://192.168.61.18:2379 
|| 596e1e583604dc35 | started | etcd03 | https://192.168.61.22:2380 | https://192.168.61.22:2379 
|| 71f26872cb1756fc | started | etcd01 | https://192.168.61.17:2380 | https://192.168.61.17:2379 
|+------------------+---------+--------+---------------------------+---------------------------
+

#换回 v2 版本
[root@master01 ssl]# export ETCDCTL_API=2

三、部署 docker 引擎(所有 node 节点)

node1 和 node2 操作相同

[root@node01 ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
[root@node01 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@node01 ~]# yum install -y docker-ce docker-ce-cli containerd.io
[root@node01 ~]# systemctl enable --now docker

四、flannel 网络配置 

1、K8S 中 Pod 网络通信

Pod 内容器与容器之间的通信
在同一个 Pod 内的容器(Pod 内的容器是不会跨宿主机的)共享同一个网络命令空间,相当于它们在同一台机器上一样,可以用 localhost 地址访问彼此的端口。

同一个 Node 内 Pod 之间的通信
每个 Pod 都有一个真实的全局 IP 地址,同一个 Node 内的不同 Pod 之间可以直接采用对方 Pod 的 IP 地址进行通信,Pod1 与 Pod2 都是通过 Veth 连接到同一个 docker0 网桥,网段相同,所以它们之间可以直接通信。

不同 Node 上 Pod 之间的通信
Pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 Node 之间的通信只能通过宿主机的物理网卡进行。
要想实现不同 Node 上 Pod 之间的通信,就必须想办法通过主机的物理网卡 IP 地址进行寻址和通信。因此要满足两个条件:Pod 的 IP 不能冲突,将 Pod 的 IP 和所在的 Node 的 IP 关联起来,通过这个关联让不同 Node 上 Pod 之间直接通过内网 IP 地址通信。

2、Overlay Network

叠加网络,在二层或者三层网络上叠加的一种虚拟网络技术模式,该网络中的主机通过虚拟链路隧道连接起来(类似于 VPN)。

3、 VXLAN

将源数据包封装到 UDP 中,并使用基础网络的 IP/MAC 作为外层报文头进行封装,然后在以太网上传输,到达目的地后由隧道端点解封装并将数据发送给目标地址。

4、Flannel 简介

Flannel 的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。Flannel 是 Overlay 网络的一种,将 TCP 源数据包封装在另一种网络包里面进行路由转发和通信,目前支持 UDP、VXLAN、host-GW 三种数据转发方式。

5、Flannel 工作原理

数据从 node01 上 Pod 的源容器中发出后,经由所在主机的 docker0 虚拟网卡转发到 flannel.1 虚拟网卡,flanneld 服务监听在 flanne.1 数据网卡的另外一端。
Flannel 通过 Etcd 服务维护了一张节点间的路由表。源主机 node01 的 flanneld 服务将原本的数据内容封装到 UDP 中后根据自己的路由表通过物理网卡投递给目的节点 node02 的 flanneld 服务,数据到达以后被解包,然后直接进入目的节点的 flannel.1 虚拟网卡,之后被转发到目的主机的 docker0 虚拟网卡,最后就像本机容器通信一样由 docker0 转发到目标容器。

6、ETCD 之 Flannel 功能说明

  • 存储管理 Flannel 可分配的 IP 地址段资源
  • 监控 ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表

7、Flannel 部署

7.1  在 master01 节点上操

添加 flannel 网络配置信息,写入分配的子网段到 etcd 中,供 flannel 使用

[root@master01 /opt/etcd/ssl]# etcdctl --ca-file=ca.pem --cert-file=server.pem --key-file=server-key.pem --endpoints="https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.61.22:2379" set /coreos.com/network/config '{"Network":"172.17.0.0/16","Backend":{"Type":"vxlan"}}'
......

#------------------------------------------------#
etcdctl \
--ca-file=ca.pem \
--cert-file=server.pem \
--key-file=server-key.pem \
--endpoints="https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.61.22:2379" \
set /coreos.com/network/config '{"Network":"172.17.0.0/16","Backend":{"Type":"vxlan"}}'

查看写入的信息

etcdctl \
--ca-file=ca.pem \
--cert-file=server.pem \
--key-file=server-key.pem \
--endpoints="https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.61.22:2379" \
get /coreos.com/network/config

set :给键赋值
set /coreos.com/network/config:添加一条网络配置记录,这个配置将用于 flannel 分配给每个 docker 的虚拟 IP 地址段
get :获取网络配置记录,后面不用再跟参数
Network:用于指定 Flannel 地址池
Backend:用于指定数据包以什么方式转发,默认为 udp 模式,Backend 为 vxlan 比起预设的 udp 性能相对好一些。

7.2  在所有 node 节点上操作

node1 和 node2 操作相同

安装 flannel

[root@node01 ~]# cd /opt
#上传 flannel 安装包 flannel-v.0.10.0-linux-amd64.tar.gz
[root@node01 /opt]#tar xf flannel-v0.10.0-linux-amd64.tar.gz
[root@node01 /opt]# ls
flanneld	#flanneld 为主要的执行文件
mk-docker-opts.sh	#mk-docker-opts.sh 脚本用于生成 Docker 启动参数

编写 flannel.sh 脚本

[root@node01 /opt]#vim flannel.sh
#!/bin/bash

#定义etcd集群的端点IP地址和对外提供服务的2379端口
#${var:-string}:若变量var为空,则用在命令行中用string来替换;否则变量var不为空时,则用变量var的值来替换,这里的1代表的是位置变量$1
ETCD_ENDPOINTS=${1:-"http://127.0.0.1:2379"}

#创建flanneld配置文件
cat > /opt/kubernetes/cfg/flanneld <<EOF
FLANNEL_OPTIONS="--etcd-endpoints=${ETCD_ENDPOINTS} \\
-etcd-cafile=/opt/etcd/ssl/ca.pem \\
-etcd-certfile=/opt/etcd/ssl/server.pem \\
-etcd-keyfile=/opt/etcd/ssl/server-key.pem"
EOF

#flanneld 本应使用 etcd 客户端TLS相关证书(client 证书),这里全部都使用同一套证书认证。


#创建flanneld.service服务管理文件
cat > /usr/lib/systemd/system/flanneld.service <<EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service

[Service]
Type=notify
EnvironmentFile=/opt/kubernetes/cfg/flanneld
ExecStart=/opt/kubernetes/bin/flanneld --ip-masq \$FLANNEL_OPTIONS
ExecStartPost=/opt/kubernetes/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=on-failure

[Install]
WantedBy=multi-user.target

EOF

#flanneld启动后会使用 mk-docker-opts.sh 脚本生成 docker 网络相关配置信息
#mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS:将组合选项键设置为环境变量DOCKER_NETWORK_OPTIONS,docker启动时将使用此变量
#mk-docker-opts.sh -d /run/flannel/subnet.env:指定要生成的docker网络相关信息配置文件的路径,docker启动时候引用此配置

systemctl daemon-reload
systemctl enable flanneld
systemctl restart flanneld


>>>>>>>>>>>>>>>wq

 创建 kubenetes 工作目录

[root@node01 opt]# mkdir -p /opt/kubernetes/{cfg,bin,ssl}
[root@node01 opt]# mv mk-docker-opts.sh flanneld /opt/kubernetes/bin/

启动 flannel 服务,开启 flannel 网络功能

[root@node01 opt]# chmod +x flannel.sh 
[root@node01 opt]# ./flannel.sh https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.61.22:2379
[root@node01 opt]# systemctl status flanneld.service | grep Active
   Active: active (running) since 三 2021-12-15 16:19:44 CST; 7s ago
  • flannel 启动后会生成一个 docker 网络相关信息配置文件 /run/flannel/subnet.env,包含了 docker 要使用 flannel 通讯的相关参数

node1

[root@node01 /opt]#cat /run/flannel/subnet.env
DOCKER_OPT_BIP="--bip=172.17.8.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=false"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_NETWORK_OPTIONS=" --bip=172.17.8.1/24 --ip-masq=false --mtu=1450"

node2

[root@node02 opt]# cat /run/flannel/subnet.env
DOCKER_OPT_BIP="--bip=172.17.65.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=false"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_NETWORK_OPTIONS=" --bip=172.17.65.1/24 --ip-masq=false --mtu=1450"

–bip:指定 docker 启动时的子网
–ip-masq:设置 ipmasq=false 关闭 snat 伪装策略
–mtu=1450:mtu 要留出 50 字节给外层的 vxlan 封包的额外开销使用 

7.3  修改 docker0 网卡网段与 flannel 一致 

  • 添加 docker 环境变量
[root@node01 opt]# vim /lib/systemd/system/docker.service 

#13行,插入环境文件
EnvironmentFile=/run/flannel/subnet.env
#14行,在原有变量中间添加变量$DOCKER_NETWORK_OPTIONS
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS -H fd:// --containerd=/run/containerd/containerd.sock
[root@node01 opt]# systemctl daemon-reload
[root@node01 opt]# systemctl restart docker
  • 查看node1 发现 docker0 与 flannel 已经一致
[root@node01 /opt]#ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.8.1  netmask 255.255.255.0  broadcast 172.17.8.255
        ether 02:42:1d:b3:78:10  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 172.17.8.0  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::c02a:3bff:fea1:8c05  prefixlen 64  scopeid 0x20<link>
        ether c2:2a:3b:a1:8c:05  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 27 overruns 0  carrier 0  collisions 0        
  • 查看node2 发现 docker0 与 flannel 已经一致
[root@node02 /opt]#ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.65.1  netmask 255.255.255.0  broadcast 172.17.65.255
        ether 02:42:6a:97:84:b1  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0



flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 172.17.65.0  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::8c5:b2ff:fed4:7a77  prefixlen 64  scopeid 0x20<link>
        ether 0a:c5:b2:d4:7a:77  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 26 overruns 0  carrier 0  collisions 0

7.4  容器间跨网通信 

  • node1
[root@node01 ~]# docker pull centos:7
......
[root@node01 ~]# docker run -itd centos:7 bash
22ded9906dc3c86c673dd161d02eb5f9a3c8b195a6287f3c84a8b7dc989b170a

[root@node01 /opt]#docker ps -a
CONTAINER ID   IMAGE      COMMAND   CREATED          STATUS          PORTS     NAMES
22ded9906dc3   centos:7   "bash"    20 seconds ago   Up 18 seconds             determined_joliot

[root@node01 ~]# docker exec -it 22ded9906dc3 bash
[root@22ded9906dc3 /]# yum -y install net-tools
[root@22ded9906dc3 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 172.17.8.2  netmask 255.255.255.0  broadcast 172.17.8.255
        ether 02:42:ac:11:08:02  txqueuelen 0  (Ethernet)
        RX packets 28919  bytes 21577152 (20.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16406  bytes 889342 (868.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
......
  • node2
[root@node02 ~]# docker pull centos:7
......
[root@node02 ~]# docker run -itd centos:7 bash
f92c4b891679046f1ee934b52284650ae5eb80e7ec7d30ab0b1e50207329f751
[root@node02 opt]# docker ps -a 
CONTAINER ID   IMAGE      COMMAND   CREATED          STATUS          PORTS     NAMES
f92c4b891679   centos:7   "bash"    35 seconds ago   Up 34 seconds             modest_carver

[root@node02 opt]# docker exec -it f92c4b891679 bash
[root@f92c4b891679 /]# yum -y install net-tools
[root@f92c4b891679 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 172.17.5.2  netmask 255.255.255.0  broadcast 172.17.5.255
        ether 02:42:ac:11:05:02  txqueuelen 0  (Ethernet)
        RX packets 27742  bytes 21477141 (20.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12791  bytes 694102 (677.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
......
[root@f92c4b891679 /]# ping -I 172.17.65.2 172.17.8.2 
PING 172.17.8.2 (172.17.8.2) from 172.17.65.2 : 56(84) bytes of data.
64 bytes from 172.17.8.2: icmp_seq=1 ttl=62 time=0.660 ms
64 bytes from 172.17.8.2: icmp_seq=2 ttl=62 time=0.429 ms
64 bytes from 172.17.8.2: icmp_seq=3 ttl=62 time=0.688 ms
64 bytes from 172.17.8.2: icmp_seq=4 ttl=62 time=1.68 ms
^C
--- 172.17.8.2 ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 8019ms
rtt min/avg/max/mdev = 0.391/0.802/1.686/0.480 ms
  • node1
[root@22ded9906dc3 /]# ping -I 172.17.8.2 172.17.65.2
PING 172.17.65.2 (172.17.65.2) from 172.17.8.2 : 56(84) bytes of data.
64 bytes from 172.17.65.2: icmp_seq=1 ttl=62 time=0.533 ms
64 bytes from 172.17.65.2: icmp_seq=2 ttl=62 time=0.398 ms
64 bytes from 172.17.65.2: icmp_seq=3 ttl=62 time=0.458 ms
64 bytes from 172.17.65.2: icmp_seq=4 ttl=62 time=0.461 ms
64 bytes from 172.17.65.2: icmp_seq=5 ttl=62 time=0.510 ms
^C
--- 172.17.65.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4010ms
rtt min/avg/max/mdev = 0.398/0.472/0.533/0.046 ms

五、部署 master 组件(master01 节点)

1、编写 apiserver.sh、scheduler.sh、controller-manager.sh

1.1  编写 apiserver.sh

[root@master01 ~]# cd /k8s
[root@master01 k8s]# vim apiserver.sh 
#!/bin/bash
#example: apiserver.sh 192.168.61.17 https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.61.22:2379
#创建 kube-apiserver 启动参数配置文件
MASTER_ADDRESS=$1
ETCD_SERVERS=$2

cat >/opt/kubernetes/cfg/kube-apiserver <<EOF
KUBE_APISERVER_OPTS="--logtostderr=true \\
--v=4 \\
--etcd-servers=${ETCD_SERVERS} \\
--bind-address=${MASTER_ADDRESS} \\
--secure-port=6443 \\
--advertise-address=${MASTER_ADDRESS} \\
--allow-privileged=true \\
--service-cluster-ip-range=10.0.0.0/24 \\
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \\
--authorization-mode=RBAC,Node \\
--kubelet-https=true \\
--enable-bootstrap-token-auth \\
--token-auth-file=/opt/kubernetes/cfg/token.csv \\
--service-node-port-range=30000-50000 \\
--tls-cert-file=/opt/kubernetes/ssl/apiserver.pem  \\
--tls-private-key-file=/opt/kubernetes/ssl/apiserver-key.pem \\
--client-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--etcd-cafile=/opt/etcd/ssl/ca.pem \\
--etcd-certfile=/opt/etcd/ssl/server.pem \\
--etcd-keyfile=/opt/etcd/ssl/server-key.pem"
EOF

#--logtostderr=true:输出日志到标准错误控制台,不输出到文件
#--v=4:指定输出日志的级别,v=4为调试级别详细输出
#--etcd-servers:指定etcd服务器列表(格式://ip:port),逗号分隔
#--bind-address:指定 HTTPS 安全接口的监听地址,默认值0.0.0.0
#--secure-port:指定 HTTPS 安全接口的监听端口,默认值6443
#--advertise-address:通过该 ip 地址向集群其他节点公布 api server 的信息,必须能够被其他节点访问
#--allow-privileged=true:允许拥有系统特权的容器运行,默认值false
#--service-cluster-ip-range:指定 Service Cluster IP 地址段
#--enable-admission-plugins:kuberneres集群的准入控制机制,各控制模块以插件的形式依次生效,集群时必须包含ServiceAccount,运行在认证(Authentication)、授权(Authorization)之后,Admission Control是权限认证链上的最后一环, 对请求API资源对象进行修改和校验
#--authorization-mode:在安全端口使用RBAC,Node授权模式,未通过授权的请求拒绝,默认值AlwaysAllow。RBAC是用户通过角色与权限进行关联的模式;Node模式(节点授权)是一种特殊用途的授权模式,专门授权由kubelet发出的API请求,在进行认证时,先通过用户名、用户分组验证是否是集群中的Node节点,只有是Node节点的请求才能使用Node模式授权
#--kubelet-https=true:kubelet通信使用https,默认值true
#--enable-bootstrap-token-auth:在apiserver上启用Bootstrap Token 认证
#--token-auth-file=/opt/kubernetes/cfg/token.csv:指定Token认证文件路径
#--service-node-port-range:指定 NodePort 的端口范围,默认值30000-32767


#创建 kube-apiserver.service 服务管理文件
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
ExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable kube-apiserver
systemctl restart kube-apiserver

>>>>>>>>>>>>wq

1.2  编写 scheduler.sh 

[root@master01 k8s]# vim scheduler.sh 
#!/bin/bash
#创建 kube-scheduler 启动参数配置文件
MASTER_ADDRESS=$1
 
cat >/opt/kubernetes/cfg/kube-scheduler <<EOF
KUBE_SCHEDULER_OPTS="--logtostderr=true \\
--v=4 \\
--master=${MASTER_ADDRESS}:8080 \\
--leader-elect=true"
EOF

#--master:监听 apiserver 的地址和8080端口
#--leader-elect=true:启动 leader 选举
#k8s中Controller-Manager和Scheduler的选主逻辑:k8s中的etcd是整个集群所有状态信息的存储,涉及数据的读写和多个etcd之间数据的同步,对数据的一致性要求严格,所以使用较复杂的 raft 算法来选择用于提交数据的主节点。而 apiserver 作为集群入口,本身是无状态的web服务器,多个 apiserver 服务之间直接负载请求并不需要做选主。Controller-Manager 和 Scheduler 作为任务类型的组件,比如 controller-manager 内置的 k8s 各种资源对象的控制器实时的 watch apiserver 获取对象最新的变化事件做期望状态和实际状态调整,调度器watch未绑定节点的pod做节点选择,显然多个这些任务同时工作是完全没有必要的,所以 controller-manager 和 scheduler 也是需要选主的,但是选主逻辑和 etcd 不一样的,这里只需要保证从多个 controller-manager 和 scheduler 之间选出一个 leader 进入工作状态即可,而无需考虑它们之间的数据一致和同步。

 
#创建 kube-scheduler.service 服务管理文件
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
ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
Restart=on-failure
 
[Install]
WantedBy=multi-user.target
EOF
 
systemctl daemon-reload
systemctl enable kube-scheduler
systemctl restart kube-scheduler

1.3  编写 controller-manager.sh

[root@master01 k8s]# vim controller-manager.sh 
#!/bin/bash
#创建 kube-controller-manager 启动参数配置文件
MASTER_ADDRESS=$1
 
cat >/opt/kubernetes/cfg/kube-controller-manager <<EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true \\
--v=4 \\
--master=${MASTER_ADDRESS}:8080 \\
--leader-elect=true \\
--address=127.0.0.1 \\
--service-cluster-ip-range=10.0.0.0/24 \\
--cluster-name=kubernetes \\
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \\
--root-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--experimental-cluster-signing-duration=87600h0m0s"
EOF

#--cluster-name=kubernetes:集群名称,与CA证书里的CN匹配
#--cluster-signing-cert-file:指定签名的CA机构根证书,用来签名为 TLS BootStrapping 创建的证书和私钥
#--root-ca-file:指定根CA证书文件路径,用来对 kube-apiserver 证书进行校验,指定该参数后,才会在 Pod 容器的 ServiceAccount 中放置该 CA 证书文件
#--experimental-cluster-signing-duration:设置为 TLS BootStrapping 签署的证书有效时间为10年,默认为1年

 
#创建 kube-controller-manager.service 服务管理文件
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
ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
 
[Install]
WantedBy=multi-user.target
EOF
 
systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl restart kube-controller-manager

2、编写 k8s-cert.sh 

  • 注意要把编写apiserver-csr.json的注释删掉!!!否则会报错!
[root@master01 k8s]# vim k8s-cert.sh 
#!/bin/bash
#配置证书生成策略,让 CA 软件知道颁发有什么功能的证书,生成用来签发其他组件证书的根证书
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF

#生成CA证书和私钥(根证书和私钥)
cat > ca-csr.json <<EOF
{
    "CN": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing",
      	    "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

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


#-----------------------
#生成 apiserver 的证书和私钥(apiserver和其它k8s组件通信使用)
#hosts中将所有可能作为 apiserver 的 ip 添加进去,后面 keepalived 使用的 VIP 也要加入
cat > apiserver-csr.json <<EOF
{
    "CN": "kubernetes",
    "hosts": [
#service
      "10.0.0.1",
#本地
      "127.0.0.1",
#master01
      "192.168.61.17",
#master02
      "192.168.61.21",	
#vip,后面 keepalived 使用
      "192.168.61.31",	
#load balancer01(master)
      "192.168.61.32",
#load balancer02(backup)
      "192.168.61.33",
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

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


#-----------------------
#生成 kubectl 的证书和私钥,具有admin权限
cat > admin-csr.json <<EOF
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
EOF

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


#-----------------------
#生成 kube-proxy 的证书和私钥
cat > kube-proxy-csr.json <<EOF
{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

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

>>>>>>>>>>>wq
  • 赋予权限

chmod +x *.sh

3、创建 kubernetes 工作目录

[root@master01 k8s]# mkdir -p /opt/kubernetes/{cfg,bin,ssl}

4、生成 CA 证书、相关组件的证书和私钥

[root@master01 k8s]# mkdir /k8s/k8s-cert
[root@master01 k8s]# mv /k8s/k8s-cert.sh /k8s/k8s-cert
[root@master01 k8s]# cd !$
cd /k8s/k8s-cert
[root@master01 k8s-cert]# ./k8s-cert.sh
#生成CA证书、相关组件的证书和私钥
[root@master01 k8s-cert]# ls
admin.csr       admin.pem           apiserver-key.pem  ca.csr       ca.pem          kube-proxy-csr.json
admin-csr.json  apiserver.csr       apiserver.pem      ca-csr.json  k8s-cert.sh     kube-proxy-key.pem
admin-key.pem   apiserver-csr.json  ca-config.json     ca-key.pem   kube-proxy.csr  kube-proxy.pem

5、复制 CA 证书、apiserver 相关证书和私钥到 kubernetes 工作目录的 ssl 子目录中

[root@master01 k8s-cert]# ls *.pem
admin-key.pem  apiserver-key.pem  ca-key.pem  kube-proxy-key.pem
admin.pem      apiserver.pem      ca.pem      kube-proxy.pem
[root@master01 k8s-cert]# cp ca*pem apiserver*pem /opt/kubernetes/ssl/

6、下载或上传 kubernetes 安装包到 /k8s 目录,并解压

[root@master01 k8s-cert]# cd /k8s/
[root@master01 k8s]# rz -E
#上传k8s安装包kubernetes-server-linux-amd64.tar.gz
rz waiting to receive.
[root@master01 k8s]# tar zxvf kubernetes-server-linux-amd64.tar.gz 

7、复制 master 组件的关键命令文件到 kubernetes 工作目录的 bin 子目录中

[root@master01 k8s]# cd /k8s/kubernetes/server/bin/
[root@master01 bin]# ls
apiextensions-apiserver              kubeadm                    kube-controller-manager.docker_tag  kube-proxy.docker_tag      mounter
cloud-controller-manager             kube-apiserver             kube-controller-manager.tar         kube-proxy.tar
cloud-controller-manager.docker_tag  kube-apiserver.docker_tag  kubectl                             kube-scheduler
cloud-controller-manager.tar         kube-apiserver.tar         kubelet                             kube-scheduler.docker_tag
hyperkube                            kube-controller-manager    kube-proxy                          kube-scheduler.tar
[root@master01 bin]# cp kube-apiserver kubectl kube-controller-manager kube-scheduler /opt/kubernetes/bin/
[root@master01 bin]# ln -s /opt/kubernetes/bin/* /usr/local/bin/

 8、创建 bootstrap token 认证文件

  • apiserver 启动时会调用,然后就相当于在集群内创建了一个这个用户,接下来就可以用 RBAC 给他授权
[root@master01 bin]# cd /k8s/
[root@master01 k8s]# vim token.sh

#!/bin/bash
#获取随机数前16个字节内容,以十六进制格式输出,并删除其中空格
BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
#生成token.csv文件,按照Token序列号,用户名,UID,用户组的格式生成
cat > /opt/kubernetes/cfg/token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"sysytem:kubelet-bootstrap"
EOF

>>>>>>>>>wq

[root@master01 k8s]# chmod +x token.sh 
[root@master01 k8s]# ./token.sh 
[root@master01 k8s]# cat /opt/kubernetes/cfg/token.csv 
51f89e29018c04f782be79dbc66a4ef6,kubelet-bootstrap,10001,"sysytem:kubelet-bootstrap"

9、二进制文件、token、证书都准备好后,开启 apiserver 服务

[root@master01 /k8s]# ./apiserver.sh 192.168.61.17 https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.61.22:2379
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-apiserver.service to /usr/lib/systemd/system/kube-apiserver.service.

10、检查

10.1  检查进程是否启动成功

  • k8s 通过 kube-apiserver 这个进程提供服务,该进程运行在单个 master 节点上。默认有两个端口 6443 和 8080(新版本为 58080)
[root@master01 k8s]# ps -aux | grep kube-apiserver
root       5829  8.7  8.6 419932 335216 ?       Ssl  17:44   0:28 /opt/kubernetes/bin/kube-apiserver --logtostderr=true --v=4 --etcd-servers=https://192.168.61.17:2379,https://192.168.61.18:2379,https://192.168.
61.22:2379 --bind-address=192.168.61.17 --secure-port=6443 --advertise-address=192.168.61.17 --allow-privileged=true --service-cluster-ip-range=10.0.0.0/24 --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction --authorization-mode=RBAC,Node --kubelet-https=true --enable-bootstrap-token-auth --token-auth-file=/opt/kubernetes/cfg/token.csv --service-node-port-range=30000-50000 --tls-cert-file=/opt/kubernetes/ssl/apiserver.pem --tls-private-key-file=/opt/kubernetes/ssl/apiserver-key.pem --client-ca-file=/opt/kubernetes/ssl/ca.pem --service-account-key-file=/opt/kubernetes/ssl/ca-key.pem --etcd-cafile=/opt/etcd/ssl/ca.pem --etcd-certfile=/opt/etcd/ssl/server.pem --etcd-keyfile=/opt/etcd/ssl/server-key.pemroot       5905  0.0  0.0 112676   980 pts/0    S+   17:49   0:00 grep --color=auto kube-apiserver

10.2  检查 6443 端口

  • 安全端口 6443 用于接收 HTTPS 请求,用于基于 Token 文件或客户端证书等认证
[root@master01 k8s]# netstat -natp | grep 6443
tcp        0      0 192.168.61.17:6443       0.0.0.0:*               LISTEN      5829/kube-apiserver 
tcp        0      0 192.168.61.17:6443       192.168.61.17:37526      ESTABLISHED 5829/kube-apiserver 
tcp        0      0 192.168.61.17:37526      192.168.61.17:6443       ESTABLISHED 5829/kube-apiserver 

10.3  检查 8080 端口

  • 本地端口 8080 用于接收 HTTP 请求,非认证或授权的 HTTP 请求通过该端口访问 API Server
[root@master01 k8s]# netstat -natp | grep 8080
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      5829/kube-apiserver

10.4  查看版本信息

  • 必须保证 apiserver 启动正常,不然无法查询到 server 的版本信息
[root@master01 k8s]# kubectl version
Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.3", GitCommit:"435f92c719f279a3a67808c80521ea17d5715c66", GitTreeState:"clean", BuildDate:"2018-11-26T12:57:14Z", GoVersion:"go1.10.4", Com
piler:"gc", Platform:"linux/amd64"}Server Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.3", GitCommit:"435f92c719f279a3a67808c80521ea17d5715c66", GitTreeState:"clean", BuildDate:"2018-11-26T12:46:57Z", GoVersion:"go1.10.4", Com
piler:"gc", Platform:"linux/amd64"}

11 、启动 scheduler 服务

[root@master01 /opt/k8s]# ./scheduler.sh 127.0.0.1
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-scheduler.service to /usr/lib/systemd/system/kube-scheduler.service.

[root@master01 k8s]# ps aux|grep kube-scheduler
root       6023  5.5  0.5  46128 19572 ?        Ssl  17:52   0:00 /opt/kubernetes/bin/kube-scheduler --logtostderr=true --v=4 --master=127.0.0.1:8080 --leader-elect=true
root       6051  0.0  0.0 112676   980 pts/0    S+   17:53   0:00 grep --color=auto kube-scheduler

12、启动 controller-manager 服务

[root@master01 /k8s]# ./controller-manager.sh 127.0.0.1
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-controller-manager.service to /usr/lib/systemd/system/kube-controller-manager.service.

[root@master01 k8s]# ps aux | grep controller-manager
root       6112 14.3  1.5 136504 58080 ?        Ssl  17:53   0:01 /opt/kubernetes/bin/kube-controller-manager --logtostderr=true --v=4 --master=127.0.0.1:8080 --leader-elect=true --address=127.0.0.1 --service-
cluster-ip-range=10.0.0.0/24 --cluster-name=kubernetes --cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem --cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem --root-ca-file=/opt/kubernetes/ssl/ca.pem --service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem --experimental-cluster-signing-duration=87600h0m0sroot       6131  0.0  0.0 112676   980 pts/0    S+   17:53   0:00 grep --color=auto controller-manager

13、查看 master 节点状态

[root@master01 /k8s]# kubectl get componentstatuses
NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok                  
scheduler            Healthy   ok                  
etcd-1               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"}   
etcd-2               Healthy   {"health":"true"}   

六、 部署 Worker Node 组件

1、把 kubelet、kube-proxy 拷贝到 node 节点(master01 节点)

[root@master01 k8s]# cd /k8s/kubernetes/server/bin
[root@master01 bin]# scp kubelet kube-proxy root@192.168.3.12:/opt/kubernetes/bin/
                                                                                                 
[root@master01 bin]# scp kubelet kube-proxy root@192.168.3.13:/opt/kubernetes/bin/                

2、编写脚本(node01 节点)

2.1  编写proxy.sh

[root@node01 opt]# vim proxy.sh 
#!/bin/bash
 
NODE_ADDRESS=$1

#创建 kube-proxy 启动参数配置文件
cat >/opt/kubernetes/cfg/kube-proxy <<EOF
KUBE_PROXY_OPTS="--logtostderr=true \\
--v=4 \\
--hostname-override=${NODE_ADDRESS} \\
--cluster-cidr=172.17.0.0/16 \\
--proxy-mode=ipvs \\
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"
EOF

#--hostnameOverride: 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node,从而不会创建任何 ipvs 规则
#--cluster-cidr:指定 Pod 网络使用的聚合网段,Pod 使用的网段和 apiserver 中指定的 service 的 cluster ip 网段不是同一个网段。 kube-proxy 根据 --cluster-cidr 判断集群内部和外部流量,指定 --cluster-cidr 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT,即来自非 Pod 网络的流量被当成外部流量,访问 Service 时需要做 SNAT。
#--proxy-mode:指定流量调度模式为 ipvs 模式
#--kubeconfig: 指定连接 apiserver 的 kubeconfig 文件	

 
#----------------------
#创建 kube-proxy.service 服务管理文件
cat >/usr/lib/systemd/system/kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Proxy
After=network.target
 
[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-proxy
ExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure
 
[Install]
WantedBy=multi-user.target
EOF
 
systemctl daemon-reload
systemctl enable kube-proxy
systemctl restart kube-proxy

>>>>>>>wq

2.2  编写 kubelet.sh

[root@node01 opt]# vim kubelet.sh 
#!/bin/bash
 
NODE_ADDRESS=$1
DNS_SERVER_IP=${2:-"10.0.0.2"}

#创建 kubelet 启动参数配置文件
cat >/opt/kubernetes/cfg/kubelet <<EOF
KUBELET_OPTS="--logtostderr=true \\
--v=4 \\
--hostname-override=${NODE_ADDRESS} \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
--config=/opt/kubernetes/cfg/kubelet.config \\
--cert-dir=/opt/kubernetes/ssl \\
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"
EOF

#--hostname-override:指定kubelet节点在集群中显示的主机名或IP地址,默认使用主机hostname;kube-proxy和kubelet的此项参数设置必须完全一致
#--kubeconfig:指定kubelet.kubeconfig文件位置,用于如何连接到apiserver,里面含有kubelet证书,master授权完成后会在node节点上生成 kubelet.kubeconfig 文件
#--bootstrap-kubeconfig:指定连接 apiserver 的 bootstrap.kubeconfig 文件
#--config:指定kubelet配置文件的路径,启动kubelet时将从此文件加载其配置
#--cert-dir:指定master颁发的客户端证书和密钥保存位置
#--pod-infra-container-image:指定Pod基础容器(Pause容器)的镜像。Pod启动的时候都会启动一个这样的容器,每个pod之间相互通信需要Pause的支持,启动Pause需要Pause基础镜像

 
#----------------------
#创建kubelet配置文件(该文件实际上就是一个yml文件,语法非常严格,不能出现tab键,冒号后面必须要有空格,每行结尾也不能有空格)
cat >/opt/kubernetes/cfg/kubelet.config <<EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: ${NODE_ADDRESS}
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS:
- ${DNS_SERVER_IP} 
clusterDomain: cluster.local.
failSwapOn: false
authentication:
  anonymous:
    enabled: true
EOF

#PS:当命令行参数与此配置文件(kubelet.config)有相同的值时,就会覆盖配置文件中的该值。

 
#----------------------
#创建 kubelet.service 服务管理文件
cat >/usr/lib/systemd/system/kubelet.service <<EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
 
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet
ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
KillMode=process
 
[Install]
WantedBy=multi-user.target
EOF
 
systemctl daemon-reload
systemctl enable kubelet
systemctl restart kubelet

2.3  赋予上述脚本执行权限

[root@node01 opt]# chmod +x *.sh

3、在 master01 节点上操作

3.1  创建用于生成 kubelet 的配置文件的目录

[root@master01 ~]# mkdir /k8s/kubeconfig

3.2  编写 kubeconfig.sh

kubeconfig.sh 文件包含集群参数(CA 证书、API Server 地址),客户端参数(上面生成的证书和私钥),集群 context 上下文参数(集群名称、用户名)。Kubenetes 组件(如 kubectl、kube-proxy)通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群,连接到 apiserver。

[root@master01 ~]# cd /k8s/kubeconfig

[root@master01 kubeconfig]# vim kubeconfig.sh 
#!/bin/bash
#example: kubeconfig 192.168.61.17 /opt/k8s/k8s-cert/
#创建bootstrap.kubeconfig文件
#该文件中内置了 token.csv 中用户的 Token,以及 apiserver CA 证书;kubelet 首次启动会加载此文件,使用 apiserver CA 证书建立与 apiserver 的 TLS 通讯,使用其中的用户 Token 作为身份标识向 apiserver 发起 CSR 请求
 
BOOTSTRAP_TOKEN=$(awk -F ',' '{print $1}' /opt/kubernetes/cfg/token.csv)
APISERVER=$1
SSL_DIR=$2
 
export KUBE_APISERVER="https://$APISERVER:6443"

# 设置集群参数
kubectl config set-cluster kubernetes \
  --certificate-authority=$SSL_DIR/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=bootstrap.kubeconfig
#--embed-certs=true:表示将ca.pem证书写入到生成的bootstrap.kubeconfig文件中

# 设置客户端认证参数,kubelet 使用 bootstrap token 认证
kubectl config set-credentials kubelet-bootstrap \
  --token=${BOOTSTRAP_TOKEN} \
  --kubeconfig=bootstrap.kubeconfig

# 设置上下文参数
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kubelet-bootstrap \
  --kubeconfig=bootstrap.kubeconfig

# 使用上下文参数生成 bootstrap.kubeconfig 文件
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

#----------------------

#创建kube-proxy.kubeconfig文件
# 设置集群参数
kubectl config set-cluster kubernetes \
  --certificate-authority=$SSL_DIR/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kube-proxy.kubeconfig

# 设置客户端认证参数,kube-proxy 使用 TLS 证书认证
kubectl config set-credentials kube-proxy \
  --client-certificate=$SSL_DIR/kube-proxy.pem \
  --client-key=$SSL_DIR/kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig

# 设置上下文参数
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig

# 使用上下文参数生成 kube-proxy.kubeconfig 文件
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
 
[root@master01 kubeconfig]# chmod +x kubeconfig.sh

3.3  生成 kubelet 的配置文件

[root@master01 kubeconfig]# cd /k8s/kubeconfig
[root@master01 kubeconfig]# chmod +x kubeconfig.sh 
[root@master01 kubeconfig]# ./kubeconfig.sh 192.168.3.11 /k8s/k8s-cert/
[root@master01 kubeconfig]# ls
bootstrap.kubeconfig  kubeconfig.sh  kube-proxy.kubeconfig

3.4  把配置文件 bootstrap.kubeconfig、kube-proxy.kubeconfig 拷贝到 node 节点

[root@master01 kubeconfig]# cd /k8s/kubeconfig
[root@master01 kubeconfig]# scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.3.12:/opt/kubernetes/cfg/
......
[root@master01 kubeconfig]# scp bootstrap.kubeconfig kube-proxy.kubeconfig root@192.168.3.13:/opt/kubernetes/cfg/
......

3.5  RBAC 授权及相关说明

将预设用户 kubelet-bootstrap 与内置的 ClusterRole system:node-bootstrapper 绑定到一起,使其能够发起 CSR 请求

[root@master01 /k8s/kubeconfig]# cd /opt/
[root@master01 /opt]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
clusterrolebinding.rbac.authorization.k8s.io/kubelet-bootstrap created

kubelet 采用 TLS Bootstrapping 机制,自动完成到 kube-apiserver 的注册,在 node 节点量较大或者后期自动扩容时非常有用。
Master apiserver 启用 TLS 认证后,node 节点 kubelet 组件想要加入集群,必须使用 CA 签发的有效证书才能与 apiserver 通信,当 node 节点很多时,前述证书是一件很繁琐的事情。因此 Kubernetes 引入了 TLS bootstrapping 机制来自动颁发客户端证书,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。
kubelet 首次启动通过加载 bootstrap.kubeconfig 中的用户 Token 和 apiserver CA 证书发起首次 CSR 请求,这个 Token 被预先内置在 apiserver 节点的 token.csv 中,其身份为 kubelet=bootstrap 用户和 system:kubelet=bootstrap 用户组;想要首次 CSR 请求能成功(即不会被 apiserver 401 拒绝),则需要先创建一个 ClusterRoleBinding,将 kubelet-bootstrap 用户和 system:node-bootstrapper 内置 ClusterRole 绑定(通过 kubectl get clusterroles 可查询),使其能够发起 CSR 认证请求。
TLS bootstrapping 时的证书实际是由 kube-controller-manager 组件来签署的,也就是说证书有效期是 kube-controller-manager 组件控制的;kube-controller-manager 组件提供一个 --experimental-cluster-signing-duration 参数来设置签署的证书有效时间:默认为 8760h0m0s,将其改为 87600h0m0s,即 10 年后再进行 TLS bootstrapping 签署证书即可。
也就是说 kubelet 首次访问 API Server 时,是使用 token 做认证,通过后,Controller Manager 会为 kubelet 生成一个证书,以后的访问都是用证书做认证了。

3.6  查看角色

[root@master01 ~]# kubectl get clusterroles | grep system:node-bootstrapper
system:node-bootstrapper                                               55m

3.7   查看已授权的角色

[root@master01 opt]# kubectl get clusterrolebinding
NAME                                                   AGE
cluster-admin                                          55m
kubelet-bootstrap                                      83s
system:aws-cloud-provider                              55m
system:basic-user                                      55m
system:controller:attachdetach-controller              55m
system:controller:certificate-controller               55m
system:controller:clusterrole-aggregation-controller   55m
system:controller:cronjob-controller                   55m
system:controller:daemon-set-controller                55m
system:controller:deployment-controller                55m
system:controller:disruption-controller                55m
system:controller:endpoint-controller                  55m
system:controller:expand-controller                    55m
system:controller:generic-garbage-collector            55m
system:controller:horizontal-pod-autoscaler            55m
system:controller:job-controller                       55m
system:controller:namespace-controller                 55m
system:controller:node-controller                      55m
system:controller:persistent-volume-binder             55m
system:controller:pod-garbage-collector                55m
system:controller:pv-protection-controller             55m
system:controller:pvc-protection-controller            55m
system:controller:replicaset-controller                55m
system:controller:replication-controller               55m
system:controller:resourcequota-controller             55m
system:controller:route-controller                     55m
system:controller:service-account-controller           55m
system:controller:service-controller                   55m
system:controller:statefulset-controller               55m
system:controller:ttl-controller                       55m
system:discovery                                       55m
system:kube-controller-manager                         55m
system:kube-dns                                        55m
system:kube-scheduler                                  55m
system:node                                            55m
system:node-proxier                                    55m
system:volume-scheduler                                55m

4、在 node1 节点上操作

4.1  使用 kubelet.sh 脚本启动 kubelet 服务

[root@node01 opt]# cd /opt
[root@node01 opt]# chmod +x kubelet.sh
[root@node01 opt]# ./kubelet.sh 192.168.61.18
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /usr/lib/systemd/system/kubelet.service.

4.2  检查 kubelet 服务启动

[root@node01 /opt]#ps aux | grep kubelet
root      17594  1.0  1.1 469776 44284 ?        Ssl  18:50   0:00 /opt/kubernetes/bin/kubelet --logtostderr=true --v=4 --hostname-override=192.168.3.12 --kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig --boo
tstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig --config=/opt/kubernetes/cfg/kubelet.config --cert-dir=/opt/kubernetes/ssl --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0root      17636  0.0  0.0 112676   980 pts/0    S+   18:50   0:00 grep --color=auto kubelet

4.3  查看当前 ssl 目录

[root@node01 opt]# ls /opt/kubernetes/ssl/
kubelet-client.key.tmp  kubelet.crt  kubelet.key


此时还没有生成证书,因为 master 还未对此申请做批准操作

5、在 master01 节点上操作

5.1  查看 CSR 请求

[root@master01 opt]# kubectl get csr
NAME                                                   AGE    REQUESTOR           CONDITION
node-csr-SqqD89LSQcjcGNkmb91SiJblbLfY8hEp-45QXYg8Y_o   2m4s   kubelet-bootstrap   Pending
  • 发现有来自于 kubelet-bootstrap 的申请,处于待办状态

5.2  通过 CSR 请求

[root@master01 opt]# kubectl certificate approve node-csr-SqqD89LSQcjcGNkmb91SiJblbLfY8hEp-45Q
XYg8Y_ocertificatesigningrequest.certificates.k8s.io/node-csr-SqqD89LSQcjcGNkmb91SiJblbLfY8hEp-45QXYg8Y_o approved

5.3  再次查看 CSR 请求状态

[root@master01 opt]# kubectl get csr
NAME                                                   AGE    REQUESTOR           CONDITION
node-csr-SqqD89LSQcjcGNkmb91SiJblbLfY8hEp-45QXYg8Y_o   6m2s   kubelet-bootstrap   Approved,Issued
  • Approved,Issued 表示已授权 CSR 请求并签发整数

5.4  查看集群节点状态

  • 已成功接入node01节点
[root@master01 opt]# kubectl get nodes
NAME           STATUS   ROLES    AGE    VERSION
192.168.61.18   Ready    <none>   117s   v1.12.3

6、在 node01 节点上操作

6.1  已自动生成证书和 kubelet.kubeconfig 文件

[root@node01 /opt]# ls /opt/kubernetes/cfg/kubelet.kubeconfig
/opt/kubernetes/cfg/kubelet.kubeconfig
[root@node01 /opt]#ls /opt/kubernetes/ssl
kubelet-client-2021-12-15-18-55-02.pem  kubelet-client-current.pem  kubelet.crt  kubelet.key

6.2  加载 ip_vs 模块

[root@node01 /opt]# for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i > /dev/null 2>&1 && /sbin/modprobe $i;done
ip_vs_dh
ip_vs_ftp
ip_vs
ip_vs_lblc
ip_vs_lblcr
ip_vs_lc
ip_vs_nq
ip_vs_pe_sip
ip_vs_rr
ip_vs_sed
ip_vs_sh
ip_vs_wlc
ip_vs_wrr

6.3  使用 proxy.sh 脚本启动 proxy 服务

[root@node01 /opt]# chmod +x proxy.sh 
[root@node01 /opt]# ./proxy.sh 192.168.3.12
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-proxy.service to /usr/lib/systemd/system/kube-proxy.service.

[root@node01 /opt]#systemctl status kube-proxy.service 
● kube-proxy.service - Kubernetes Proxy
   Loaded: loaded (/usr/lib/systemd/system/kube-proxy.service; enabled; vendor preset: disable
d)   Active: active (running) since 三 2021-12-15 19:02:04 CST; 6s ago
......

7、node02 节点部署

7.1   在 node01 节点操作

  • 将 kubelet.sh、proxy.sh 文件拷贝到 node02 节点
[root@node01 opt]# cd /opt/
[root@node01 opt]# scp kubelet.sh proxy.sh root@192.168.61.22:`pwd`

7.2  在 node02 节点上操作

使用 kubelet.sh 脚本启动 kubelet 服务

[root@node02 opt]# cd /opt
[root@node02 opt]# chmod +x kubelet.sh
[root@node02 opt]# ./kubelet.sh 192.168.61.22
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /usr/lib/systemd/system/kubelet.service.

7.3  在 master01 节点上操作

  • 查看 CSR 请求
[root@master01 opt]# kubectl get csr
NAME                                                   AGE   REQUESTOR           CONDITION
node-csr-SqqD89LSQcjcGNkmb91SiJblbLfY8hEp-45QXYg8Y_o   17m   kubelet-bootstrap   Approved,Issued
node-csr-UH2O16Dy_-CRrunss0g8-mMuR-_PnCYerwvC1noBfv8   14s   kubelet-bootstrap   Pending
  • 通过 CSR 请求
[root@master01 opt]# kubectl certificate approve node-csr-UH2O16Dy_-CRrunss0g8-mMuR-_PnCYerwvC
1noBfv8certificatesigningrequest.certificates.k8s.io/node-csr-UH2O16Dy_-CRrunss0g8-mMuR-_PnCYerwvC1noBfv8 approved
  • 再次查看 CSR 请求
[root@master01 opt]# kubectl get csr
NAME                                                   AGE   REQUESTOR           CONDITION
node-csr-SqqD89LSQcjcGNkmb91SiJblbLfY8hEp-45QXYg8Y_o   18m   kubelet-bootstrap   Approved,Issued
node-csr-UH2O16Dy_-CRrunss0g8-mMuR-_PnCYerwvC1noBfv8   62s   kubelet-bootstrap   Approved,Issued
  • 查看集群中的节点状态
[root@master01 opt]# kubectl get nodes
NAME           STATUS   ROLES    AGE   VERSION
192.168.61.18   Ready    <none>   14m   v1.12.3
192.168.61.22   Ready    <none>   67s   v1.12.3

7.4  node02 操作

  • 加载 ipvs 模块
[root@node02 /opt]# for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i > /dev/null 2>&1 && /sbin/modprobe $i;done
ip_vs_dh
ip_vs_ftp
ip_vs
ip_vs_lblc
ip_vs_lblcr
ip_vs_lc
ip_vs_nq
ip_vs_pe_sip
ip_vs_rr
ip_vs_sed
ip_vs_sh
ip_vs_wlc
ip_vs_wrr
  • 使用 proxy.sh 脚本启动 proxy 服务
[root@node02 opt]# cd /opt
[root@node02 opt]# chmod +x proxy.sh 
[root@node02 opt]# ./proxy.sh 192.168.3.13
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-proxy.service to /usr/lib/systemd/system/kube-proxy.service.
  • 查看服务状态
[root@node02 opt]# systemctl status kube-proxy.service
● kube-proxy.service - Kubernetes Proxy
   Loaded: loaded (/usr/lib/systemd/system/kube-proxy.service; enabled; vendor preset: disable
d)   Active: active (running) since 三 2021-12-15 19:11:19 CST; 14s ago
......

8、K8S 单节点测试

master01

[root@master01 opt]# kubectl create deployment nginx-test --image=nginx:1.14
deployment.apps/nginx-test created
[root@master01 opt]# kubectl get pod	#等待镜像拉取
NAME                          READY   STATUS              RESTARTS   AGE
nginx-test-7dc4f9dcc9-vs2p6   0/1     ContainerCreating   0          5s
[root@master01 opt]# kubectl get pod	#容器启动成功
NAME                          READY   STATUS    RESTARTS   AGE
nginx-test-7dc4f9dcc9-vs2p6   1/1     Running   0          45s

查看 pod 详情 

[root@master01 opt]# kubectl describe pod nginx-test-7dc4f9dcc9-b5bqv
Name:               nginx-test-7dc4f9dcc9-b5bqv
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               192.168.61.18/192.168.61.18
......

查看 pod 额外信息(包括 IP)

[root@master01 opt]# kubectl get pod -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP           NODE           NOMINATED NODE
nginx-test-7dc4f9dcc9-b5bqv   1/1     Running   0          2m21s   172.17.8.3   192.168.61.18   <none>

使用任意 node 节点访问 pod 测试

[root@node01 /opt]#curl 172.17.8.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


版权声明:本文为HB199753原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。