前言
本文将介绍如何使用二进制文件手动搭建 Kubernetes v1.20 集群。通过这种方法,我们可以更好地理解 Kubernetes 的内部工作原理,并具备更大的灵活性和控制权。下面将逐步构建 Kubernetes 集群,并进一步了解其各个组件之间的交互和配置。
K8s的CNI网络插件理论请参考:Kubernetes的CNI网络插件介绍-CSDN博客
目录
1. 上传 master.zip 和 k8s-cert.sh
5. 上传 kubernetes-server-linux-amd64.tar.gz
11. 生成 kubectl 连接集群的 kubeconfig 文件
2.1 把 kubelet、kube-proxy 拷贝到 node 节点
4.1 检查到 node01 节点的 kubelet 发起的 CSR 请求
4.3 再次查看 Kubernetes 中所有证书签发请求 (CSR) 的列表
1.2 node02 节点部署 kubelet、proxy 服务
一、常见的 K8S 部署方式
1. Minikube
Minikube是一个工具,可以在本地快速运行一个单节点微型K8S,仅用于学习、预览K8S的一些特性使用。
部署地址:Install Tools | Kubernetes
2. Kubeadmin
Kubeadmin也是一个工具,提供kubeadm init和kubeadm join,用于快速部署K8S集群,相对简单。
Kubeadm | Kubernetes部署地址:Kubeadm | Kubernetes
3. 二进制安装部署
生产首选,从官方下载发行版的二进制包,手动部署每个组件和自签TLS证书,组成K8S集群,新手推荐。
发布 ·Kubernetes/Kubernetes (github.com)部署地址:发布 ·Kubernetes/Kubernetes (github.com)
二、环境配置
1. 集群节点配置
机器内存有限,按需自行分配:
节点名称 | IP | 部署组件 | 配置 |
k8s集群master01 | 192.168.190.100 | kube-apiserver kube-controller-manager kube-scheduler | 2C/3G |
k8s集群master02 | 192.168.190.101 | kube-apiserver kube-controller-manager kube-scheduler | 2C/3G |
k8s集群node01 | 192.168.190.102 | kubelet kube-proxy docker | 2C/2G |
k8s集群node02 | 192.168.190.103 | kubelet kube-proxy docker | 2C/2G |
etcd集群etcd01 | 192.168.190.100 | etcd | |
etcd集群etcd02 | 192.168.190.102 | etcd | |
etcd集群etcd03 | 192.168.190.103 | etcd | |
负载均衡nkmaster | 192.168.190.104 | nginx+keepalive01 | 1C/1G |
负载均衡nkbackup | 192.168.190.105 | nginx+keepalive02 | 1C/1G |
2. 操作系统初始化配置
① 关闭防火墙及其他规则
所有节点操作:
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
# 清空iptables防火墙的规则,包括过滤规则、NAT规则、Mangle规则以及自定义链
setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config
② 关闭 swap
所有节点操作:
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 在/etc/fstab文件中找到包含swap的行,并在这些行之前加上#,从而注释掉这些行
③ 根据规划设置主机名
192.168.190.100:
hostnamectl set-hostname master01
192.168.190.101:
hostnamectl set-hostname master02
192.168.190.102:
hostnamectl set-hostname node01
192.168.190.103:
hostnamectl set-hostname node02
④ 在 master01 添加 hosts
cat >> /etc/hosts << EOF
192.168.190.100 master01
192.168.190.101 master02
192.168.190.102 node01
192.168.190.103 node02
EOF
⑤ 调整内核参数
所有节点操作:
cat > /etc/sysctl.d/k8s.conf << EOF
#开启网桥模式,可将网桥的流量传递给iptables链
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#关闭ipv6协议
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF
sysctl --system
# 重新加载内核参数设置
⑥ 时间同步
所有机器均需要同步:
yum install ntpdate -y
ntpdate time.windows.com
3. 部署 docker 引擎
所有 node 节点部署 docker 引擎:
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
systemctl start docker.service
systemctl enable docker.service
docker --version
Docker version 26.1.2, build 211e74b
三、部署 etcd 集群
etcd 目前默认使用2379端口提供HTTP API服务, 2380端口和peer通信(这两个端口已经被IANA(互联网数字分配机构)官方预留给etcd)。 即etcd默认使用2379端口对外为客户端提供通讯,使用端口2380来进行服务器间内部通讯。
1. 准备签发证书环境
在 master01 节点上操作
1.1 准备 cfssl 证书生成工具
CFSSL 是 CloudFlare 公司开源的一款 PKI/TLS 工具。CFSSL 包含一个命令行工具和一个用于签名、验证和捆绑 TLS 证书的 HTTP API 服务,使用Go语言编写。
准备cfssl证书生成工具:
[root@master01 ~]# wget https://github.com/cloudflare/cfssl/releases/download/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
[root@master01 ~]# wget https://github.com/cloudflare/cfssl/releases/download/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson
[root@master01 ~]# wget https://github.com/cloudflare/cfssl/releases/download/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo
[root@master01 ~]# chmod +x /usr/local/bin/cfssl*
# cfssl:证书签发的工具命令
# cfssljson:将 cfssl 生成的证书(json格式)变为文件承载式证书
# cfssl-certinfo:验证证书的信息
# cfssl-certinfo -cert <证书名称> 查看证书的信息
[root@master01 ~]# cd /usr/local/bin/
[root@master01 bin]# ls
cfssl cfssl-certinfo cfssljson
1.2 创建存放 etcd 证书目录
[root@master01 ~]# mkdir /opt/k8s
[root@master01 ~]# cd /opt/k8s/
1.3 上传 etcd-cert.sh 和 etcd.sh
到 /opt/k8s/ 目录中
[root@master01 k8s]# rz -E
rz waiting to receive.
[root@master01 k8s]# ls
etcd-cert.sh etcd.sh
[root@master01 k8s]# chmod +x *.sh
① etcd.sh:
#!/bin/bash
#example: ./etcd.sh etcd01 192.168.190.100 etcd02=https://192.168.190.102:2380,etcd03=https://192.168.190.103: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 \
--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 \
--logger=zap \
--enable-v2
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
#--enable-v2:开启 etcd v2 API 接口。当前 flannel 版本不支持 etcd v3 通信
#--logger=zap:使用 zap 日志框架。zap.Logger 是go语言中相对日志库中性能最高的
#--peer开头的配置项用于指定集群内部TLS相关证书(peer 证书),这里全部都使用同一套证书认证
#不带--peer开头的的参数是指定 etcd 服务器TLS相关证书(server 证书),这里全部都使用同一套证书认证
systemctl daemon-reload
systemctl enable etcd
systemctl restart etcd
② etcd-cert.sh:
#!/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.190.100",
"192.168.190.102",
"192.168.190.103"
],
"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
1.4 创建证书私钥目录
创建用于生成CA证书、etcd 服务器证书以及私钥的目录
[root@master01 k8s]# mkdir /opt/k8s/etcd-cert
[root@master01 k8s]# mv etcd-cert.sh etcd-cert/
[root@master01 k8s]# cd etcd-cert/
[root@master01 etcd-cert]# ./etcd-cert.sh
# 生成CA证书、etcd 服务器证书以及私钥
[root@master01 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
1.5 启动 etcd 服务
上传 etcd-v3.4.9-linux-amd64.tar.gz 到 /opt/k8s 目录中
[root@master01 etcd-cert]# cd /opt/k8s/
[root@master01 k8s]# https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz
[root@master01 k8s]# rz -E
rz waiting to receive.
[root@master01 k8s]# ls
etcd-cert etcd.sh etcd-v3.4.9-linux-amd64.tar.gz
[root@master01 k8s]# tar zxvf etcd-v3.4.9-linux-amd64.tar.gz
[root@master01 k8s]# ls etcd-v3.4.9-linux-amd64
Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
# etcd就是etcd 服务的启动命令,后面可跟各种启动参数
# etcdctl主要为etcd 服务提供了命令行操作
1.6 创建配置文件证书目录
创建用于存放 etcd 配置文件,命令文件,证书的目录
[root@master01 k8s]# mkdir -p /opt/etcd/{cfg,bin,ssl}
[root@master01 k8s]# cd etcd-v3.4.9-linux-amd64/
[root@master01 etcd-v3.4.9-linux-amd64]# ls
Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
[root@master01 etcd-v3.4.9-linux-amd64]# mv etcd etcdctl /opt/etcd/bin/
[root@master01 ~]# cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/
[root@master01 ~]# cd /opt/k8s/
[root@master01 k8s]# ./etcd.sh etcd01 192.168.190.100 etcd02=https://192.168.190.102:2380,etcd03=https://192.168.190.103:2380
# 进入卡住状态等待其他节点加入,这里需要三台etcd服务同时启动,如果只启动其中一台后,服务会卡在那里,直到集群中所有etcd节点都已启动,可忽略这个情况
可另外打开一个窗口查看etcd进程是否正常:
ps -ef | grep etcd
1.7 拷贝 etcd 文件至其他节点
把 etcd 相关证书文件、命令文件和服务管理文件全部拷贝到另外两个 etcd 集群节点
[root@master01 k8s]# scp -r /opt/etcd/ root@node01:/opt/
[root@master01 k8s]# scp -r /opt/etcd/ root@node02:/opt/
[root@master01 k8s]# scp /usr/lib/systemd/system/etcd.service root@node01:/usr/lib/systemd/system/
[root@master01 k8s]# scp /usr/lib/systemd/system/etcd.service root@node02:/usr/lib/systemd/system/
2. 修改 node02 etcd 配置文件
2.1 修改 etcd 配置文件
[root@node01 ~]# vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd02"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.190.102:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.190.102:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.190.102:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.190.102:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.190.100:2380,etcd02=https://192.168.190.102:2380,etcd03=https://192.168.190.103:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
2.2 启动 etcd 服务
[root@node01 ~]# systemctl enable --now etcd.service
[root@node01 ~]# systemctl status etcd.service
● etcd.service - Etcd Server
Loaded: loaded (/usr/lib/systemd/system/etcd.service; enabled; vendor preset: disabled)
Active: active (running) since 一 2024-05-13 15:25:28 CST; 3s ago
Main PID: 39561 (etcd)
3. 修改 node03 etcd 配置文件
node02 节点上操作
3.1 修改 etcd 配置文件
[root@node02 ~]# vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd03"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.190.103:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.190.103:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.190.103:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.190.103:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.190.100:2380,etcd02=https://192.168.190.102:2380,etcd03=https://192.168.190.103:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
3.2 启动 etcd 服务
[root@node02 ~]# systemctl enable --now etcd.service
Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service.
[root@node02 ~]# systemctl status etcd.service
● etcd.service - Etcd Server
Loaded: loaded (/usr/lib/systemd/system/etcd.service; enabled; vendor preset: disabled)
Active: active (running) since 一 2024-05-13 15:28:18 CST; 15s ago
Main PID: 6783 (etcd)
4. 检查 etcd 群集状态
[root@master01 k8s]# ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.190.100:2379,https://192.168.190.102:2379,https://192.168.190.103:2379" endpoint health --write-out=table
+------------------------------+--------+-------------+-------+
| ENDPOINT | HEALTH | TOOK | ERROR |
+------------------------------+--------+-------------+-------+
| https://192.168.190.100:2379 | true | 26.529107ms | |
| https://192.168.190.102:2379 | true | 30.65982ms | |
| https://192.168.190.103:2379 | true | 34.404428ms | |
+------------------------------+--------+-------------+-------+
[root@master01 k8s]# ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.190.100:2379,https://192.168.190.102:2379,https://192.168.190.103: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.190.100:2379 | 89d026e8ec4cd7cf | 3.4.9 | 20 kB | true | false | 834 | 9 | 9 | |
| https://192.168.190.102:2379 | 98639068bd0e31f3 | 3.4.9 | 20 kB | false | false | 834 | 9 | 9 | |
| https://192.168.190.103:2379 | e8ed9fc61074cf0b | 3.4.9 | 20 kB | false | false | 834 | 9 | 9 | |
+------------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
# --cert-file:识别HTTPS端使用SSL证书文件
# --key-file:使用此SSL密钥文件标识HTTPS客户端
# --ca-file:使用此CA证书验证启用https的服务器的证书
# --endpoints:集群中以逗号分隔的机器地址列表
# cluster-health:检查etcd集群的运行状况
5. 查看 etcd 集群成员列表
[root@master01 k8s]# ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.190.100:2379,https://192.168.190.102:2379,https://192.168.190.103:2379" --write-out=table member list
+------------------+---------+--------+------------------------------+------------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+--------+------------------------------+------------------------------+------------+
| 89d026e8ec4cd7cf | started | etcd01 | https://192.168.190.100:2380 | https://192.168.190.100:2379 | false |
| 98639068bd0e31f3 | started | etcd02 | https://192.168.190.102:2380 | https://192.168.190.102:2379 | false |
| e8ed9fc61074cf0b | started | etcd03 | https://192.168.190.103:2380 | https://192.168.190.103:2379 | false |
+------------------+---------+--------+------------------------------+------------------------------+------------+
6. 快照与还原
① 需要将所有 etcd 节点均挂起再进行快照
② 同样的,需要将其它正在运行的 etcd 节点均挂起,再进行还原需要的 etcd 节点;即一台一台还原,且还原过程中,其他 etcd 节点挂起。
四、部署 Master 组件
master 组件签发证书。
1. 上传 master.zip 和 k8s-cert.sh
到 /opt/k8s 目录中,解压 master.zip 压缩包,在 master01 节点上操作
[root@master01 ~]# cd /opt/k8s/
[root@master01 k8s]# rz -E
rz waiting to receive.
[root@master01 k8s]# ls
etcd-cert etcd-v3.4.9-linux-amd64 k8s-cert.sh
etcd.sh etcd-v3.4.9-linux-amd64.tar.gz master.zip
[root@master01 k8s]# chmod +x *.sh
2. 创建 kubernetes 工作目录
[root@master01 k8s]# mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
3. 创建 CA证书私钥目录
创建用于生成CA证书、相关组件的证书和私钥的目录
[root@master01 k8s]# mkdir /opt/k8s/k8s-cert
[root@master01 k8s]# ls
admin.sh etcd-cert etcd-v3.4.9-linux-amd64.tar.gz master.zip
apiserver.sh etcd.sh k8s-cert scheduler.sh
controller-manager.sh etcd-v3.4.9-linux-amd64 k8s-cert.sh
[root@master01 k8s]# mv k8s-cert.sh /opt/k8s/k8s-cert
[root@master01 k8s]# cd /opt/k8s/k8s-cert/
[root@master01 k8s-cert]# ./k8s-cert.sh # 生成CA证书、相关组件的证书和私钥
[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
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": [
"10.0.0.1",
"127.0.0.1",
"192.168.190.100",
"192.168.190.101",
"192.168.190.200",
"192.168.190.104",
"192.168.190.105",
"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
~
4. 拷贝证书私钥
复制CA证书、apiserver相关证书和私钥到 kubernetes工作目录的 ssl 子目录中
[root@master01 k8s-cert]# cp ca*pem apiserver*pem /opt/kubernetes/ssl/
5. 上传 kubernetes-server-linux-amd64.tar.gz
到 /opt/k8s/ 目录中,解压 kubernetes 压缩包
下载地址:https://github.com/kubernetes/kubernetes/blob/release-1.20/CHANGELOG/CHANGELOG-1.20.md
# 下载一个server包就够了,包含了Master和Worker Node二进制文件
[root@master01 k8s-cert]# cd /opt/k8s/
[root@master01 k8s]# rz -E
rz waiting to receive.
[root@master01 k8s]# ls
admin.sh etcd.sh kubernetes-server-linux-amd64.tar.gz
apiserver.sh etcd-v3.4.9-linux-amd64 master.zip
controller-manager.sh etcd-v3.4.9-linux-amd64.tar.gz scheduler.sh
etcd-cert k8s-cert
[root@master01 k8s]# tar zxvf kubernetes-server-linux-amd64.tar.gz
6. 拷贝 master 组件
复制master组件的关键命令文件到 kubernetes工作目录的 bin 子目录中
[root@master01 k8s]# cd /opt/k8s/kubernetes/server/bin
[root@master01 bin]# ls
apiextensions-apiserver kube-controller-manager kube-proxy.docker_tag
kubeadm kube-controller-manager.docker_tag kube-proxy.tar
kube-aggregator kube-controller-manager.tar kube-scheduler
kube-apiserver kubectl kube-scheduler.docker_tag
kube-apiserver.docker_tag kubelet kube-scheduler.tar
kube-apiserver.tar kube-proxy mounter
[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/
7. 创建 bootstrap token 认证文件
apiserver 启动时会调用,然后就相当于在集群内创建了一个这个用户,接下来就可以用 RBAC 给他授权。
[root@master01 bin]# cd /opt/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,"system:kubelet-bootstrap"
EOF
[root@master01 k8s]# chmod +x token.sh
[root@master01 k8s]# ./token.sh
[root@master01 k8s]# cat /opt/kubernetes/cfg/token.csv
274f2e00534834783724d7f3a61c7f2e,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
8. 开启 apiserver 服务
二进制文件、token、证书都准备好后,开启 apiserver 服务。
apiserver.sh:
#!/bin/bash
#example: apiserver.sh 192.168.190.100 https://192.168.190.100:2379,https://192.168.190.102:2379,https://192.168.190.103:2379
#创建 kube-apiserver 启动参数配置文件
MASTER_ADDRESS=$1
ETCD_SERVERS=$2
cat >/opt/kubernetes/cfg/kube-apiserver <<EOF
KUBE_APISERVER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--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 \\
--enable-bootstrap-token-auth=true \\
--token-auth-file=/opt/kubernetes/cfg/token.csv \\
--service-node-port-range=30000-50000 \\
--kubelet-client-certificate=/opt/kubernetes/ssl/apiserver.pem \\
--kubelet-client-key=/opt/kubernetes/ssl/apiserver-key.pem \\
--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 \\
--service-account-issuer=api \\
--service-account-signing-key-file=/opt/kubernetes/ssl/apiserver-key.pem \\
--etcd-cafile=/opt/etcd/ssl/ca.pem \\
--etcd-certfile=/opt/etcd/ssl/server.pem \\
--etcd-keyfile=/opt/etcd/ssl/server-key.pem \\
--requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \\
--proxy-client-cert-file=/opt/kubernetes/ssl/apiserver.pem \\
--proxy-client-key-file=/opt/kubernetes/ssl/apiserver-key.pem \\
--requestheader-allowed-names=kubernetes \\
--requestheader-extra-headers-prefix=X-Remote-Extra- \\
--requestheader-group-headers=X-Remote-Group \\
--requestheader-username-headers=X-Remote-User \\
--enable-aggregator-routing=true \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
EOF
#--logtostderr=true:启用日志。输出日志到标准错误控制台,不输出到文件
#--v=4:日志等级。指定输出日志的级别,v=4为调试级别详细输出
#--etcd-servers:etcd集群地址。指定etcd服务器列表(格式://ip:port),逗号分隔
#--bind-address:监听地址。指定 HTTPS 安全接口的监听地址,默认值0.0.0.0
#--secure-port:https安全端口。指定 HTTPS 安全接口的监听端口,默认值6443
#--advertise-address:集群通告地址。通过该 ip 地址向集群其他节点公布 api server 的信息,必须能够被其他节点访问
#--allow-privileged=true:启用授权。允许拥有系统特权的容器运行,默认值false
#--service-cluster-ip-range:Service虚拟IP地址段。指定 Service Cluster IP 地址段
#--enable-admission-plugins:准入控制模块。kuberneres集群的准入控制机制,各控制模块以插件的形式依次生效,集群时必须包含ServiceAccount,运行在认证(Authentication)、授权(Authorization)之后,Admission Control是权限认证链上的最后一环, 对请求API资源对象进行修改和校验
#--authorization-mode:认证授权,启用RBAC授权和节点自管理。在安全端口使用RBAC,Node授权模式,未通过授权的请求拒绝,默认值AlwaysAllow。RBAC是用户通过角色与权限进行关联的模式;Node模式(节点授权)是一种特殊用途的授权模式,专门授权由kubelet发出的API请求,在进行认证时,先通过用户名、用户分组验证是否是集群中的Node节点,只有是Node节点的请求才能使用Node模式授权
#--enable-bootstrap-token-auth:启用TLS bootstrap机制。在apiserver上启用Bootstrap Token 认证
#--token-auth-file=/opt/kubernetes/cfg/token.csv:指定bootstrap token认证文件路径
#--service-node-port-range:指定 Service NodePort 的端口范围,默认值30000-32767
#–-kubelet-client-xxx:apiserver访问kubelet客户端证书
#--tls-xxx-file:apiserver https证书
#1.20版本必须加的参数:–-service-account-issuer,–-service-account-signing-key-file
#--etcd-xxxfile:连接Etcd集群证书
#–-audit-log-xxx:审计日志
#启动聚合层相关配置:–requestheader-client-ca-file,–proxy-client-cert-file,–proxy-client-key-file,–requestheader-allowed-names,–requestheader-extra-headers-prefix,–requestheader-group-headers,–requestheader-username-headers,–enable-aggregator-routing
#创建 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
执行脚本:
[root@master01 k8s]# ./apiserver.sh 192.168.190.100 https://192.168.190.100:2379,https://192.168.190.102:2379,https://192.168.190.103:2379
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-apiserver.service to /usr/lib/systemd/system/kube-apiserver.service.
[root@master01 k8s]# ps aux | grep kube-apiserver
[root@master01 k8s]# netstat -natp | grep 6443
tcp 0 0 192.168.190.100:6443 0.0.0.0:* LISTEN 38425/kube-apiserve
tcp 0 0 192.168.190.100:57686 192.168.190.100:6443 ESTABLISHED 38425/kube-apiserve
tcp 0 0 192.168.190.100:6443 192.168.190.100:57686 ESTABLISHED 38425/kube-apiserve
9. 启动 scheduler 服务
[root@master01 k8s]# ./scheduler.sh
[root@master01 k8s]# ps aux | grep kube-scheduler
root 38559 25.4 1.0 748212 30020 ? Ssl 22:58 0:02 /opt/kubernetes/bin/kube-scheduler --logtostderr=false --v=2 --log-dir=/opt/kubernetes/logs --leader-elect=true --kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig --bind-address=127.0.0.1
root 38570 0.0 0.0 112676 988 pts/2 S+ 22:58 0:00 grep --color=auto kube-scheduler
scheduler.sh:
#!/bin/bash
##创建 kube-scheduler 启动参数配置文件
MASTER_ADDRESS=$1
cat >/opt/kubernetes/cfg/kube-scheduler <<EOF
KUBE_SCHEDULER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \\
--bind-address=127.0.0.1"
EOF
#-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群
#--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证书
cd /opt/k8s/k8s-cert/
#创建证书请求文件
cat > kube-scheduler-csr.json << EOF
{
"CN": "system:kube-scheduler",
"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 kube-scheduler-csr.json | cfssljson -bare kube-scheduler
#生成kubeconfig文件
KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
KUBE_APISERVER="https://192.168.190.100:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials kube-scheduler \
--client-certificate=./kube-scheduler.pem \
--client-key=./kube-scheduler-key.pem \
--embed-certs=true \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-scheduler \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
##创建 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
10. 启动 controller-manager 服务
[root@master01 k8s]# ./controller-manager.sh
[root@master01 k8s]# ps aux | grep kube-controller-manager
root 38670 51.2 1.7 815960 51280 ? Ssl 22:59 0:03 /opt/kubernetes/bin/kube-controller-manager --logtostderr=false --v=2 --log-dir=/opt/kubernetes/logs --leader-elect=true --kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig --bind-address=127.0.0.1 --allocate-node-cidrs=true --cluster-cidr=10.244.0.0/16 --service-cluster-ip-range=10.0.0.0/24 --cluster-signing-cert-file=/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 --cluster-signing-duration=87600h0m0s
root 38681 0.0 0.0 112676 988 pts/2 S+ 22:59 0:00 grep --color=auto kube-controller-manager
controller-manager.sh:
#!/bin/bash
##创建 kube-controller-manager 启动参数配置文件
MASTER_ADDRESS=$1
cat >/opt/kubernetes/cfg/kube-controller-manager <<EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \\
--bind-address=127.0.0.1 \\
--allocate-node-cidrs=true \\
--cluster-cidr=10.244.0.0/16 \\
--service-cluster-ip-range=10.0.0.0/24 \\
--cluster-signing-cert-file=/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 \\
--cluster-signing-duration=87600h0m0s"
EOF
#––leader-elect:当该组件启动多个时,自动选举(HA)
#-–kubeconfig:连接 apiserver 用的配置文件,用于识别 k8s 集群
#--cluster-cidr=10.244.0.0/16:pod资源的网段,需与pod网络插件的值设置一致。通常,Flannel网络插件的默认为10.244.0.0/16,Calico插件的默认值为192.168.0.0/16
#--cluster-signing-cert-file/–-cluster-signing-key-file:自动为kubelet颁发证书的CA,与apiserver保持一致。指定签名的CA机构根证书,用来签名为 TLS BootStrapping 创建的证书和私钥
#--root-ca-file:指定根CA证书文件路径,用来对 kube-apiserver 证书进行校验,指定该参数后,才会在 Pod 容器的 ServiceAccount 中放置该 CA 证书文件
#--experimental-cluster-signing-duration:设置为 TLS BootStrapping 签署的证书有效时间为10年,默认为1年
##生成kube-controller-manager证书
cd /opt/k8s/k8s-cert/
#创建证书请求文件
cat > kube-controller-manager-csr.json << EOF
{
"CN": "system:kube-controller-manager",
"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 kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
#生成kubeconfig文件
KUBE_CONFIG="/opt/kubernetes/cfg/kube-controller-manager.kubeconfig"
KUBE_APISERVER="https://192.168.190.100:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials kube-controller-manager \
--client-certificate=./kube-controller-manager.pem \
--client-key=./kube-controller-manager-key.pem \
--embed-certs=true \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-controller-manager \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
##创建 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
11. 生成 kubectl 连接集群的 kubeconfig 文件
[root@master01 k8s]# ./admin.sh
Cluster "kubernetes" set.
User "cluster-admin" set.
Context "default" created.
Switched to context "default".
admin.sh:
#!/bin/bash
mkdir /root/.kube
KUBE_CONFIG="/root/.kube/config"
KUBE_APISERVER="https://192.168.190.100:6443"
cd /opt/k8s/k8s-cert/
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials cluster-admin \
--client-certificate=./admin.pem \
--client-key=./admin-key.pem \
--embed-certs=true \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user=cluster-admin \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
12. 通过 kubectl 工具查看当前集群组件状态
[root@master01 k8s]# kubectl get cs
[root@master01 k8s]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
13. 查看版本信息
[root@master01 k8s]# kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.11", GitCommit:"27522a29febbcc4badac257763044d0d90c11abd", GitTreeState:"clean", BuildDate:"2021-09-15T19:21:44Z", GoVersion:"go1.15.15", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.11", GitCommit:"27522a29febbcc4badac257763044d0d90c11abd", GitTreeState:"clean", BuildDate:"2021-09-15T19:16:25Z", GoVersion:"go1.15.15", Compiler:"gc", Platform:"linux/amd64"}
五、部署 Worker Node 组件
在所有 node 节点上操作
1. 创建 kubernetes 工作目录
[root@node01 ~]# mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
2. 上传 node.zip
到 /opt 目录中,解压 node.zip 压缩包,获得kubelet.sh、proxy.sh
[root@node01 opt]# rz -E
rz waiting to receive.
[root@node01 opt]# ls
containerd etcd kubernetes node.zip rh
[root@node01 opt]# unzip node.zip
[root@node01 opt]# ls
containerd etcd kubelet.sh kubernetes node.zip proxy.sh rh
[root@node01 opt]# chmod +x kubelet.sh proxy.sh
2. 准备 kubelet、kube-proxy 文件
2.1 把 kubelet、kube-proxy 拷贝到 node 节点
[root@master01 k8s]# cd /opt/k8s/kubernetes/server/bin
[root@master01 bin]# ls
apiextensions-apiserver kube-controller-manager kube-proxy.docker_tag
kubeadm kube-controller-manager.docker_tag kube-proxy.tar
kube-aggregator kube-controller-manager.tar kube-scheduler
kube-apiserver kubectl kube-scheduler.docker_tag
kube-apiserver.docker_tag kubelet kube-scheduler.tar
kube-apiserver.tar kube-proxy mounter
[root@master01 bin]# scp kubelet kube-proxy root@node01:/opt/kubernetes/bin/
[root@master01 bin]# scp kubelet kube-proxy root@node02:/opt/kubernetes/bin/
2.2 上传kubeconfig.sh文件
到/opt/k8s/kubeconfig目录中
生成kubelet初次加入集群引导kubeconfig文件和kube-proxy.kubeconfig文件;
kubeconfig 文件包含集群参数(CA 证书、API Server 地址),客户端参数(上面生成的证书和私钥),集群 context 上下文参数(集群名称、用户名)。Kubenetes 组件(如 kubelet、kube-proxy)通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群,连接到 apiserver。
执行脚本:
[root@master01 bin]# mkdir /opt/k8s/kubeconfig
[root@master01 bin]# cd /opt/k8s/kubeconfig
[root@master01 kubeconfig]# rz -E
rz waiting to receive.
[root@master01 kubeconfig]# ls
kubeconfig.sh
[root@master01 kubeconfig]# vim kubeconfig.sh
[root@master01 kubeconfig]# chmod +x kubeconfig.sh
[root@master01 kubeconfig]# ./kubeconfig.sh 192.168.190.100 /opt/k8s/k8s-cert/
[root@master01 kubeconfig]# ls
bootstrap.kubeconfig kubeconfig.sh kube-proxy.kubeconfig
kubeconfig.sh:
#!/bin/bash
#example: kubeconfig 192.168.190.100 /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
2.3 拷贝配置文件到 node 节点
把配置文件 bootstrap.kubeconfig、kube-proxy.kubeconfig 拷贝到 node 节点
[root@master01 kubeconfig]# scp bootstrap.kubeconfig kube-proxy.kubeconfig root@node01:/opt/kubernetes/cfg/
[root@master01 kubeconfig]# scp bootstrap.kubeconfig kube-proxy.kubeconfig root@node02:/opt/kubernetes/cfg/
2.4 RBAC 授权
使用户 kubelet-bootstrap 能够有权限发起 CSR 请求证书
[root@master01 kubeconfig]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
clusterrolebinding.rbac.authorization.k8s.io/kubelet-bootstrap created
# 若执行失败,可先给kubectl绑定默认cluster-admin管理员集群角色,授权集群操作权限
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
3. 启动 kubelet 服务
在 node01 节点上操作
[root@node01 ~]# cd /opt/
[root@node01 opt]# ls
containerd etcd kubelet.sh kubernetes node.zip proxy.sh rh
[root@node01 opt]# ./kubelet.sh 192.168.190.102 # 填写自己的ip
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /usr/lib/systemd/system/kubelet.service.
[root@node01 opt]# ps aux | grep kubelet
root 40378 14.8 2.7 942476 50968 ? Ssl 23:08 0:01 /opt/kubernetes/bin/kubelet --logtostderr=false --v=2 --log-dir=/opt/kubernetes/logs --hostname-override=192.168.190.102 --network-plugin=cni --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
root 40391 0.0 0.0 112676 980 pts/0 S+ 23:08 0:00 grep --color=auto kubelet
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=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=${NODE_ADDRESS} \\
--network-plugin=cni \\
--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的此项参数设置必须完全一致
#--network-plugin:启用CNI
#--kubeconfig:指定kubelet.kubeconfig文件位置,当前为空路径,会自动生成,用于如何连接到apiserver,里面含有kubelet证书,master授权完成后会在node节点上生成 kubelet.kubeconfig 文件
#--bootstrap-kubeconfig:指定连接 apiserver 的 bootstrap.kubeconfig 文件
#--config:指定kubelet配置文件的路径,启动kubelet时将从此文件加载其配置
#--cert-dir:指定master颁发的kubelet证书生成目录
#--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
4. 授权 CSR 请求并签发证书
在 master01 节点上操作
4.1 检查到 node01 节点的 kubelet 发起的 CSR 请求
Pending 表示等待集群给该节点签发证书
获取Kubernetes中所有证书签发请求 (CSR) 的列表:
[root@master01 kubeconfig]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-jUqxR9_nQjM6-F3B6i06EYOLpi4tSau1jWlHGiqYLFY 36s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Pending
4.2 手动批准节点的证书签发请求
[root@master01 kubeconfig]# kubectl certificate approve node-csr-jUqxR9_nQjM6-F3B6i06EYOLpi4tSau1jWlHGiqYLFY
certificatesigningrequest.certificates.k8s.io/node-csr-jUqxR9_nQjM6-F3B6i06EYOLpi4tSau1jWlHGiqYLFY approved
4.3 再次查看 Kubernetes 中所有证书签发请求 (CSR) 的列表
[root@master01 kubeconfig]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-jUqxR9_nQjM6-F3B6i06EYOLpi4tSau1jWlHGiqYLFY 118s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
# Pending: CSR已经被创建,但还没有被审批。
# Approved: CSR已经被API服务器认可,意味着一个有权限的实体(如集群管理员)已经批准了这个签名请求。
# Denied: CSR被拒绝,通常是因为审批者认为该请求不应被批准。
# Issued: 表明CSR不仅被批准,而且证书实际上已经被签发了。
4.4 查看节点
由于网络插件还没有部署,节点会没有准备就绪 NotReady
[root@master01 kubeconfig]# kubectl get node
NAME STATUS ROLES AGE VERSION
192.168.190.102 NotReady <none> 59s v1.20.11
5. 添加负载均衡的内核模块
在 master01 节点上操作
5.1 添加 ip_vs 模块
[root@master01 ~]# 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
5.2 启动 proxy 服务
[root@node01 ~]# cd /opt/
[root@node01 opt]# ./proxy.sh 192.168.190.102
[root@node01 opt]# ps aux | grep kube-proxy
root 42044 2.4 1.5 743556 29824 ? Ssl 23:17 0:00 /opt/kubernetes/bin/kube-proxy --logtostderr=true --v=4 --hostname-override=192.168.190.102 --cluster-cidr=172.17.0.0/16 --proxy-mode=ipvs --kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig
root 42164 0.0 0.0 112676 988 pts/0 S+ 23:17 0:00 grep --color=auto kube-proxy
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模式,可添加--ipvs-scheduler选项指定ipvs调度算法(rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq)
#--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
五、部署 CNI 网络组件
1. 部署 flannel
在 node01 节点上操作:
1.1 上传 cni、flannel 安装包
上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
[root@node01 opt]# rz -E
rz waiting to receive.
[root@node01 opt]# ls
cni-plugins-linux-amd64-v0.8.6.tgz etcd kubelet.sh node.zip rh
containerd flannel.tar kubernetes proxy.sh
[root@node01 opt]# docker load -i flannel.tar # 加载docker镜像
[root@node01 opt]# mkdir /opt/cni/bin -p
[root@node01 opt]# tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin/
1.2 node02 节点部署 kubelet、proxy 服务
1.2.1 文件传输
在 node01 节点上操作:
[root@node01 ~]# cd /opt/
[root@node01 opt]# scp kubelet.sh proxy.sh root@192.168.190.103:/opt/
[root@node01 opt]# scp -r /opt/cni root@192.168.190.103:/opt/
1.2.2 启动 kubelet 服务
在 node02 节点上操作:
[root@node02 ~]# cd /opt/
[root@node02 opt]# ./kubelet.sh 192.168.190.103
1.2.3 签发证书并通过CSR请求
在 master01 节点上操作:
[root@master01 ~]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-eRjMsiTAV7Xr-hNdT1WYIJ5I2_nOM77afswwbhmiias 4m kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Pending
[root@master01 ~]# kubectl certificate approve node-csr-eRjMsiTAV7Xr-hNdT1WYIJ5I2_nOM77afswwbhmiias
[root@master01 ~]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-eRjMsiTAV7Xr-hNdT1WYIJ5I2_nOM77afswwbhmiias 4m20s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
1.2.4 加载 ipvs 模块
在 node02 节点上操作:
[root@node02 ~]# 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
1.2.5 使用proxy.sh脚本启动proxy服务
在 node02 节点上操作:
[root@node02 ~]# cd /opt/
[root@node02 opt]# ./proxy.sh 192.168.190.103
1.2.6 查看群集中的节点状态
在 master01 节点上操作:
[root@master01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.190.102 Ready <none> 39h v1.20.11
192.168.190.103 Ready <none> 4m10s v1.20.11
1.3 部署 CNI 网络
上传 kube-flannel.yml 文件到 /opt/k8s 目录中
[root@master01 k8s]# rz -E
rz waiting to receive.
[root@master01 k8s]# ls
admin.sh etcd.sh kubeconfig master.zip
apiserver.sh etcd-v3.4.9-linux-amd64 kube-flannel.yml scheduler.sh
controller-manager.sh etcd-v3.4.9-linux-amd64.tar.gz kubernetes token.sh
etcd-cert k8s-cert kubernetes-server-linux-amd64.tar.gz
[root@master01 k8s]# kubectl apply -f kube-flannel.yml
# 指定的YAML文件(kube-flannel.yml)来创建或更新Kubernetes集群中的资源
1.4 查看集群节点信息
查看kube-system命名空间中所有Pod的状态和相关信息:
[root@master01 k8s]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-mlpj6 1/1 Running 0 22m
kube-flannel-ds-qmgdw 1/1 Running 3 5m11s
# NAME: Pod的名称
# READY: 表示Pod中容器的就绪状态。这里显示1/1,表示Pod中有一个容器,且该容器已经就绪。
# STATUS: 表示Pod的整体状态。这里显示Running,表示Pod正在运行。
# RESTARTS: 表示自Pod启动以来容器重启的次数。这里显示0,表示容器没有发生重启。
# AGE: 表示Pod创建后经过的时间。这里显示2m48s,表示Pod已经运行了2分钟48秒。
获取当前Kubernetes集群中所有节点(nodes)的列表:
[root@master01 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.190.102 Ready <none> 38h v1.20.11
192.168.190.103 Ready <none> 4m10s v1.20.11
# NAME: 节点的名称,通常节点的名称可以是IP地址或者主机名。
# STATUS: 节点的状态。这里显示Ready,表示节点处于就绪状态,可以接受工作负载。
# ROLES: 节点的角色。这里显示,表示节点没有特定的角色。
# AGE: 节点的创建时间。这里显示38h,表示节点已经存在38小时。
# VERSION: Kubernetes集群中该节点的Kubernetes版本为v1.20.11。
2. 部署 Calico
Calico 与 Flannel 是两种插件(服务),这里介绍 Calico 部署,将前面的操作进行快照保存。
2.1 部署 CNI 网络
在 master01 节点上操作,上传 calico.yaml 文件到 /opt/k8s 目录中
[root@master01 ~]# cd /opt/k8s
[root@master01 k8s]# rz -E
rz waiting to receive.
[root@master01 k8s]# ls
admin.sh etcd-cert k8s-cert master.zip
apiserver.sh etcd.sh kubeconfig scheduler.sh
calico.yaml etcd-v3.4.9-linux-amd64 kubernetes token.sh
controller-manager.sh etcd-v3.4.9-linux-amd64.tar.gz kubernetes-server-linux-amd64.tar.gz
注意yml格式对齐:
[root@master01 k8s]# vim calico.yaml
- name: CALICO_IPV4POOL_CIDR
value: "10.244.0.0/16" # Calico 默认使用的网段为 192.168.0.0/16
# 修改里面定义 Pod 的网络(CALICO_IPV4POOL_CIDR),需与前面 kube-controller-manager 配置文件指定的 cluster-cidr 网段一样
[root@master01 k8s]# kubectl apply -f calico.yaml
# Kubernetes将会读取calico.yaml文件中定义的资源(如Pod、Service、Deployment等),然后在集群中创建、更新或删除这些资源,以使集群的状态与配置文件中定义的状态一致。
# 这个命令通常用于部署网络插件(如Calico)或其他Kubernetes资源配置。
2.2 查看集群组件状态
[root@master01 k8s]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-659bd7879c-qmgdw 1/1 Running 0 8m4s
calico-node-gstw5 1/1 Running 0 6m24s
calico-node-mlpj6 1/1 Running 0 8m4s
六、部署 CoreDNS
CoreDNS 可以为集群中的 service 资源创建一个域名 与 IP 的对应关系解析,可以提供稳定的、可靠的 DNS 服务,简化 Kubernetes 集群内部服务之间的通信,同时也为管理员提供了灵活的配置选项和扩展能力。
1. 上传 coredns 镜像
上传 coredns.tar 到 /opt 目录中,在所有 node 节点上操作
[root@node01 opt]# rz -E
rz waiting to receive.
[root@node01 opt]# docker load -i coredns.tar
[root@node01 opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/coreos/flannel v0.14.0 8522d622299c 2 years ago 67.9MB
k8s.gcr.io/coredns 1.7.0 bfe3a36ebd25 3 years ago 45.2MB
registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64 3.0 99e59f495ffa 8 years ago 747kB
2. Master01 节点部署 CoreDNS
上传 coredns.yaml 文件到 /opt/k8s 目录中,在 master01 节点上操作
[root@master01 ~]# cd /opt/k8s
[root@master01 k8s]# kubectl apply -f coredns.yaml
根据 coredns.yaml 文件中的配置信息,在 Kubernetes 集群中创建或更新 CoreDNS 相关的资源
[root@master01 k8s]# kubectl apply -f coredns.yaml
获取位于 kube-system 命名空间下的所有 Pod 的列表
[root@master01 k8s]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6954c77b9b-gstw5 1/1 Running 0 9s
kube-flannel-ds-mlpj6 1/1 Running 0 81m
kube-flannel-ds-qmgdw 1/1 Running 3 64m
3. DNS 解析测试
[root@master01 k8s]# kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
Error attaching, falling back to logs: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)
pod "dns-test" deleted
Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log dns-test)
如果出现以上报错,需要添加 rbac的权限 直接使用kubectl绑定 clusteradmin 管理员集群角色 授权操作权限
[root@master01 k8s]# kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
clusterrolebinding.rbac.authorization.k8s.io/cluster-system-anonymous created
[root@master01 k8s]# kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
/ # nslookup kubernetes
Server: 10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
Name: kubernetes
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local
七、小结
etcd 安装步骤:
1.准备 CA 证书和私钥文件 ,首先 CA 签发服务端证书和私有文件
2.使用 CA 证书、服务端证书 、私有文件加上 etcd 集群配置文件去启动 etcd 服务
3.复制 etcd 工作目录和管理文件到另外几个节点上(node01 node02),修改 etcd 集群配置文件并且启动 etcd 服务
4.使用 v3 版本的接口去执行 etcdctl + 证书选项(endpoint healh)| endpoint status | member list 査看 etcd 集群和节点的状态
master 组件安装:
1.先安装 apiserver
(1)准备组件相关的证书和私钥文件
(2)准备 bootstrap token 认证文件,给 kubelet 启动时签发证书使用
(3)准备组件启动配置文件
(4)启动 apiserver 服务,端口是 6443 https
2.再启动 controller-manager 和 scheduler
(1)准备启动配置文件
(2)准备相关证书和私钥文件生成 kubeconfig 文件(用于指定对接哪个 apiserver,使用什么证书认证)启动服务
3.检查集群组件状态
需要准备 kubeconfig 文件把 kubectl 加入到集群中(指定对接哪个apiserver,使用什么证书认证)
kubectl get cs
master 组件安装:
1.生成kubelet初次加入集群引导kubeconfig文件和kube-proxy.kubeconfig文件
2.把 kubelet、kube-proxy、bootstrap.kubeconfig kube-proxy.kubeconfig 拷贝到 node 节点
3.RBAC授权,使用户 kubelet-bootstrap 能够有权限发起 CSR 请求证书
4.在 node 节点启动 kubelet 服务
5.在 master 节点通过 CSR 请求并签发证书
6.在 master 节点使用命令 kubectl get node 获取集群中所有节点(Node)的信息
7.在 node 节点加载 ip_vs 模块,启动proxy服务