使用二进制方式搭建Kubernetes集群,可以更加灵活、自由地定制和配置Kubernetes。同时,它还可以实现更高的性能和更小的资源占用。
对于我这个初学者来说:
- 更加直观地看到Kubernetes的各个组件,了解它们之间的关系和作用。
- 在搭建Kubernetes集群的过程中,了解集群的架构和各个组件之间的协作关系,有助于初学者更好地理解Kubernetes的工作原理和机制。
- 使用二进制方式搭建Kubernetes集群需要进行一些配置和维护工作,这有助于初学者掌握Kubernetes的维护技能,提高自己的技术水平
1、 安装要求
在开始之前, 部署 Kubernetes 集群机器需要满足以下几个条件:
( 1) 一台或多台机器, 操作系统 CentOS7.x-86_x64
( 2) 硬件配置: 2GB 或更多 RAM, 2 个 CPU 或更多 CPU, 硬盘 30GB 或更多
( 3) 集群中所有机器之间网络互通
( 4) 可以访问外网, 需要拉取镜像, 如果服务器不能上网, 需要提前下载镜像并导入节点
( 5) 禁止 swap 分区
2、 准备环境
( 1) 软件环境:
操作系统 | CentOS7.8_x64 |
---|---|
Docker | 19-ce |
Kubernetes | 1.19 |
( 2) 服务器规划
角色 | IP | 组件 |
---|---|---|
k8s-master | 192.168.122.143 | kube-apiserver, kube-controller-manager, kube-scheduler, etcd |
k8s-node1 | 192.168.122.144 | kubelet, kube-proxy, docker etcd |
k8s-node2 | 192.168.122.145 | kubelet, kube-proxy, docker, etcd |
3、 操作系统初始化配
默认操作三个linux系统
1.关闭防火墙:
防火墙会对网络数据包进行过滤和屏蔽,可能会影响 Kubernetes 集群节点之间的通信。同时,Kubernetes 本身有较为完善的网络策略机制,可以保证集群的网络安全,因此关闭防火墙并不会对 Kubernetes 集群的安全造成影响。
systemctl stop firewalld
systemctl disable firewalld
2.关闭 selinux:
在 Kubernetes 集群中,SELinux 是一个可选的安全模块,它提供了强制访问控制和访问审计功能。但是在搭建 Kubernetes 集群时,为了简化配置和避免可能的问题,很多管理员选择将 SELinux 关闭。这主要是因为:
- SELinux 对于容器的访问控制较为严格,可能会导致一些应用程序无法正常工作或无法访问必要的资源。
- 在某些情况下,SELinux 的规则并不能很好地适应 Kubernetes 集群的安装配置,这可能会导致一些问题和错误。
- 关闭 SELinux 可以简化配置和管理工作,使得集群的部署和维护更加便捷。但是关闭 SELinux 也会降低集群的安全性和可靠性,必须在必要的时候重新启用 SELinux。
因此,关闭 SELinux 可以使 Kubernetes 集群的部署更加简单和可靠,但也会降低集群的安全性和可靠性。在实际应用中,需要根据具体情况来确定是否需要开启或关闭 SELinux。
sed -i ‘s/enforcing/disabled/’ /etc/selinux/config # 永久
setenforce 0 # 临时
3.关闭 swap:
Kubernetes 使用了 cgroup 管理容器资源。而 swap 分区可能会阻止容器使用预期的内存资源,并且可能导致应用程序在容器内部崩溃或出现其他问题。
Kubernetes 本身不会使用 swap,同时,因为容器的使用和交换内存的机制不同,如果应用程序需要使用大量内存时,容器会自动申请更多的内存,而不是使用 swap,避免了性能的损失和不可预测的行为。关闭 swap 分区可以更好地保护 Kubernetes 集群的稳定性和性能,确保容器的内存使用与性能表现的一致性。
swapoff -a # 临时
sed -ri ‘s/.swap./#&/’ /etc/fstab # 永久
4.根据规划设置主机名:
hostnamectl set-hostname
192.168.122.143 :
192.168.122.144:
192.168.122.145:
5.在 master节点中 添加 hosts:
cat >> /etc/hosts << EOF
192.168.122.143 master
192.168.122.144 node1
192.168.122.145 node2
EOF
6将桥接的 IPv4 流量传递到 iptables 的链:
在 Kubernetes 集群中,每个 Pod 都会被分配一个 IP 地址,Pod 内的容器也会被分配一个虚拟网卡和 IP 地址。当两个 Pod 之间需要通信时,它们使用这些 IP 地址进行通信。
然而,当 Pod 内的容器尝试与另一个 Pod 进行通信时,它们不会使用其 IP 地址直接发送数据包,而是会使用桥接的方式进行通信。这意味着数据包将通过 Linux 内核中的桥接设备进行传输,而不是通过网络接口发送。
为了确保这些桥接的数据包能够被正确地路由和转发,需要将它们传递到 iptables 的链中进行处理。Iptables 可以用于定义网络规则,使数据包能够正确路由到目的地。通过将桥接的 IPv4 流量传递到 iptables 的链中,可以确保 Kubernetes 集群中的 Pod 能够正确地通信,并且可以实现一些高级的网络功能,如网络策略和负载均衡等。
每个节点都要执行
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
使配置生效
sysctl --system # 生效
7.时间同步:
Kubernetes 集群中的各个节点需要相互通信进行协作,因此需要保证它们的时间是同步的,以确保它们在进行计划和调度时能够准确地协调工作。如果节点的时间不同步,则可能会出现以下问题:
- 容器运行情况出现不可预测的错误。
- 调度器无法准确计算任务的完成时间,导致任务超时或者在不合适的节点上进行调度。
- 监控和日志收集系统可能会出现时间不对齐的情况,导致数据分析的结果不准确。
因此,为了保证集群的正常运行,需要在集群中的各个节点上同步时间。
yum install ntpdate -y
ntpdate time.windows.com
注配置完以上命令最好重启linux,确保配置生效
4、 部署 Etcd 集群
Etcd 是一个分布式键值存储系统, Kubernetes 使用 Etcd 进行数据存储, 所以先准备一个 Etcd 数据库, 为解决 Etcd 单点故障, 应采用集群方式部署, 这里使用 3 台组建集群, 可容忍 1 台机器故障, 当然, 你也可以使用 5 台组建集群, 可容忍 2 台机器故障。
节点名称 | IP |
---|---|
etcd-1 | 192.168.122.143 |
etcd-2 | 192.168.122.144 |
etcd-3 | 192.168.122.145 |
注: 为了节省机器, 这里与 K8s 节点机器复用。 也可以独立于 k8s 集群之外部署, 只要apiserver 能连接到就行。
4.1 准备 cfssl 证书生成工具
CFSSL是一个基于Go语言的证书和密钥管理工具,它可以用于快速和方便地生成、签名和验证TLS证书。CFSSL支持多种证书格式和加密算法,并提供了可扩展的API,使得它可以轻松地与其他工具和应用程序集成。
可以找任意一台服务器操作, 这里使用 Master 节点
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
4.2 生成 Etcd 证书
( 1) 自签证书颁发机构( CA)
创建工作目录:
mkdir -p ~/TLS/{etcd,k8s}
cd TLS/etcd
自签 CA:
ca-config.json 文件中定义了签名配置,包括默认到期时间和不同的证书配置文件。每个证书配置文件都有自己的一组用途(usages)和到期时间。
cat > ca-config.json<< EOF
{"signing": {"default": {"expiry": "87600h"},"profiles": {"www": {"expiry": "87600h","usages": ["signing","key encipherment","server auth","client auth"]}}}
}
EOF
ca-csr.json是包含CA证书请求信息的JSON文件,ca是生成的文件前缀。
ca-csr.json 文件中定义了 etcd CA 的证书请求,包括名称、密钥。
cat > ca-csr.json<< EOF
{"CN": "etcd CA","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "Beijing","ST": "Beijing"}]
}
EOF
生成证书:
使用CFSSL命令行工具生成CA证书和密钥。
cfssl gencert -initca ca-csr.json | cfssljson -bare ca - ls *pem
ca.pem和ca-key.pem是CA证书和密钥文件
( 2) 使用自签 CA 签发 Etcd HTTPS 证书
创建证书申请文件:
server-csr.json是包含服务器证书请求信息的JSON文件
cat > server-csr.json<< EOF
{"CN": "etcd","hosts": ["192.168.122.143","192.168.122.144","192.168.122.145"],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "BeiJing","ST": "BeiJing"}]
}
EOF
注: 上述文件 hosts 字段中 IP 为所有 etcd 节点的集群内部通信 IP, 一个都不能少! 为了方便后期扩容可以多写几个预留的 IP。
(3)生成证书:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
查看
ls server*pem
server.pem是服务器的证书文件,也称为公钥证书,用于验证服务器身份;而server-key.pem则是服务器的私钥文件,用于解密客户端发送过来的加密数据。
4.3 从 Github 下载二进制文件
下载地址: https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz
4.4 部署 Etcd 集群
以下在节点 1 上操作, 为简化操作, 待会将节点 1 生成的所有文件拷贝到节点 2 和节点 3.
( 1) 解压二进制包
tar zxvf etcd-v3.4.9-linux-amd64.tar.gz
创建工作目录
mkdir -p /opt/etcd/{bin,cfg,ssl}
mv etcd-v3.4.9-linux-amd64/{etcd,etcdctl} /opt/etcd/bin/
( 2) 创建 etcd 配置文件
通过etcd.conf文件可以配置etcd的各项参数,包括集群节点的地址、数据存储路径、监听端口、证书配置等。
这里配置的是master:192.168.122.143 etcd的配置
cat > /opt/etcd/cfg/etcd.conf << EOF
#[Member]
ETCD_NAME="etcd-1"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.122.143:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.122.143:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.122.143:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.122.143:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.122.143:2380,etcd-2=https://192.168.122.144:2380,etcd-3=https://192.168.122.145:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
ETCD_NAME: 节点名称, 集群中唯一
ETCD_DATA_DIR: 数据目录
ETCD_LISTEN_PEER_URLS: 集群通信监听地址
ETCD_LISTEN_CLIENT_URLS: 客户端访问监听地址
ETCD_INITIAL_ADVERTISE_PEER_URLS: 集群通告地址
ETCD_ADVERTISE_CLIENT_URLS: 客户端通告地址
ETCD_INITIAL_CLUSTER: 集群节点地址
ETCD_INITIAL_CLUSTER_TOKEN: 集群 Token
ETCD_INITIAL_CLUSTER_STATE: 加入集群的当前状态, new 是新集群, existing 表示加入已有集群
( 3) systemd 管理 etcd
cat > /usr/lib/systemd/system/etcd.service << EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd.conf
ExecStart=/opt/etcd/bin/etcd \--cert-file=/opt/etcd/ssl/server.pem \--key-file=/opt/etcd/ssl/server-key.pem \--peer-cert-file=/opt/etcd/ssl/server.pem \--peer-key-file=/opt/etcd/ssl/server-key.pem \--trusted-ca-file=/opt/etcd/ssl/ca.pem \--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem \--logger=zap
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
( 4) 拷贝刚才生成的证书
把刚才生成的证书拷贝到配置文件中的路径
cp ~/TLS/etcd/ca*pem ~/TLS/etcd/server*pem /opt/etcd/ssl/
查看是否拷贝到指定路径
( 5) 将上面节点 1 所有生成的文件拷贝到节点 2 和节点 3
将master相关etcd的文件拷贝到ndoe1、node2中
scp -r /opt/etcd/ root@192.168.122.144:/opt/etcd/
scp -r /opt/etcd/ root@192.168.122.145:/opt/etcd/
scp /usr/lib/systemd/system/etcd.service root@192.168.122.144:/usr/lib/systemd/system/
scp /usr/lib/systemd/system/etcd.service root@192.168.122.145:/usr/lib/systemd/system/
这里一定要确认文件是否复制完成,请到指定目录下查看
然后在节点 2 和节点 3 分别修改 etcd.conf 配置文件中的节点名称和当前服务器 IP:
node2:192.168.122.144
vi /opt/etcd/cfg/etcd.conf
内容
#[Member]
ETCD_NAME="etcd-2" # 修改此处, 节点 2 改为 etcd-2, 节点 3 改为 etcd-3
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.122.144:2380" # 修改此处为当前服务器 IP
ETCD_LISTEN_CLIENT_URLS="https://192.168.122.144:2379" # 修改此处为当前服务器 IP
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.122.144:2380" # 修改此处为当前服务器 IP
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.122.144:2379" # 修改此处为当前服务器IP
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.122.143:2380,etcd-2=https://192.168.122.144:2380,etcd-3=https://192.168.122.145:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
node3:192.168.122.145
vi /opt/etcd/cfg/etcd.conf
内容
#[Member]
ETCD_NAME="etcd-3" # 修改此处, 节点 2 改为 etcd-2, 节点 3 改为 etcd-3
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.122.145:2380" # 修改此处为当前服务器 IP
ETCD_LISTEN_CLIENT_URLS="https://192.168.122.145:2379" # 修改此处为当前服务器 IP
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.122.145:2380" # 修改此处为当前服务器IP
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.122.145:2379" # 修改此处为当前服务器IP
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.122.143:2380,etcd-2=https://192.168.122.144:2380,etcd-3=https://192.168.122.145:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
这里一定要确定是否存在错误换行等错误,最好将注释去掉,以防干扰
( 6) 启动并设置开机启动
master、node1、node2依次执行systemctl start etcd,master会等待node1或node2启动
systemctl daemon-reload
systemctl start etcd
systemctl enable etcd
systemctl daemon-reload命令用于重新加载systemd的守护进程配置文件。当我们修改了systemd的配置文件时,需要使用此命令来使新的配置生效。
systemctl start etcd命令是用于启动etcd服务的命令。
systemctl enable etcd命令是用于将etcd服务设置为开机自启动。
错误
从节点启动etcd报错
请确认5,6两步是否正确。我这里是因为/opt/etcd/cfg/etcd.conf配置错误导致
( 7) 查看集群状态
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=192.168.122.143:2379,192.168.122.144:2379,192.168.122.145:2379 endpoint health
- ETCDCTL_API=3:设置 etcdctl 工具的 API 版本为 3,这是 etcd 3.x 版本所使用的 API。
- /opt/etcd/bin/etcdctl:执行 etcdctl 工具的路径。
- –cacert=/opt/etcd/ssl/ca.pem:指定 etcd 集群的根证书路径。
- –cert=/opt/etcd/ssl/server.pem:指定 etcd 集群的服务器证书路径。
- –key=/opt/etcd/ssl/server-key.pem:指定 etcd 集群的私钥路径。
- –endpoints=192.168.122.143:2379,192.168.122.144:2379,192.168.122.145:2379:指定 etcd 集群的节点地址,多个节点以逗号分隔。
- endpoint health:执行的命令,用于检查 etcd 集群的每个节点是否健康。如果返回 unhealthy,则说明该节点存在问题。
如果输出上面信息, 就说明集群部署成功。 如果有问题第一步先看日志:/var/log/message 或 journalctl -u etcd
一般都是 /opt/etcd/cfg/etcd.conf配置错误或文件拷贝错误
5、部署 Master Node
5.1 生成 kube-apiserver 证书
(1)自签证书颁发机构(CA)
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
cat > ca-csr.json<< EOF
{"CN": "kubernetes","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "Beijing","ST": "Beijing","O": "k8s","OU": "System"}]
}
EOF
cat > ca-config.json<< EOF
{"signing": {"default": {"expiry": "87600h"},"profiles": {"kubernetes": {"expiry": "87600h","usages": ["signing","key encipherment","server auth","client auth"]}}}
}
EOF
(2)生成证书:
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
查看
ls *pem
(3)使用自签 CA 签发 kube-apiserver HTTPS 证书
创建证书申请文件:
cd TLS/k8s
cat > server-csr.json<< EOF
{"CN": "kubernetes","hosts": ["10.0.0.1","127.0.0.1","192.168.122.143","192.168.122.144","192.168.122.145","192.168.122.146","192.168.122.147","192.168.122.148","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 server-csr.json |cfssljson -bare server
5.2 从 Github 下载二进制文件
下载地址:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.18.md#v1183
注:打开链接你会发现里面有很多包,下载一个 server 包就够了,包含了 Master 和Worker Node 二进制文件。
上传至服务器
5.3 解压二进制包
tar zxvf kubernetes-server-linux-amd64.tar.gz
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}cd kubernetes/server/bin
复制文件
cp kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/bin
cp kubectl /usr/bin/
5.4 部署 kube-apiserver
1. 创建配置文件
cat > /opt/kubernetes/cfg/kube-apiserver.conf << EOF
KUBE_APISERVER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--etcd-servers=https://192.168.122.143:2379,https://192.168.122.144:2379,https://192.168.122.145:2379 \\
--bind-address=192.168.122.143 \\
--secure-port=6443 \\
--advertise-address=192.168.122.143 \\
--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-32767 \\
--kubelet-client-certificate=/opt/kubernetes/ssl/server.pem \\
--kubelet-client-key=/opt/kubernetes/ssl/server-key.pem \\
--tls-cert-file=/opt/kubernetes/ssl/server.pem \\
--tls-private-key-file=/opt/kubernetes/ssl/server-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 \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
EOF
注:上面两个\ \ 第一个是转义符,第二个是换行符,使用转义符是为了使用 EOF 保留换行符。
–logtostderr:启用日志
-v:日志等级
–log-dir:日志目录
–etcd-servers:etcd 集群地址
–bind-address:监听地址
–secure-port:https 安全端口
–advertise-address:集群通告地址
–allow-privileged:启用授权
–service-cluster-ip-range:Service 虚拟 IP 地址段
–enable-admission-plugins:准入控制模块
–authorization-mode:认证授权,启用 RBAC 授权和节点自管理
–enable-bootstrap-token-auth:启用 TLS bootstrap 机制
–token-auth-file:bootstrap token 文件
–service-node-port-range:Service nodeport 类型默认分配端口范围
–kubelet-client-xxx:apiserver 访问 kubelet 客户端证书
–tls-xxx-file:apiserver https 证书
–etcd-xxxfile:连接 Etcd 集群证书
–audit-log-xxx:审计日志
2. 拷贝刚才生成的证书
把刚才生成的证书拷贝到配置文件中的路径:
cp ~/TLS/k8s/ca*pem ~/TLS/k8s/server*pem /opt/kubernetes/ssl/
3. 启用 TLS Bootstrappin
TLS Bootstraping:Master apiserver 启用 TLS 认证后,Node 节点 kubelet 和 kube- proxy 要与 kube-apiserver 进行通信,必须使用 CA 签发的有效证书才可以,当 Node节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。为了简化流程,Kubernetes 引入了 TLS bootstraping 机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。
所以强烈建议在 Node 上使用这种方式,目前主要用于 kubelet,kube-proxy 还是由我们统一颁发一个证书。
TLS bootstraping 工作流程:
创建上述配置文件中 token 文件:
cat > /opt/kubernetes/cfg/token.csv << EOF
c47ffb939f5ca36231d9e3121a252940,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF
格式:token,用户名,UID,用户组
4. systemd 管理 apiserver
cat > /usr/lib/systemd/system/kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-apiserver.conf
ExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
5. 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-apiserver
systemctl enable kube-apiserver
6. 授权 kubelet-bootstrap 用户允许请求证书
kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap
5.5 部署 kube-controller-manager
1. 创建配置文件
cat > /opt/kubernetes/cfg/kube-controller-manager.conf << EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--master=127.0.0.1:8080 \\
--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 \\
--experimental-cluster-signing-duration=87600h0m0s"
EOF
– master: 通过本地非安全本地端口 8080 连接 apiserver。
– leader-elect: 当该组件启动多个时, 自动选举( HA)
– cluster-signing-cert-file/– cluster-signing-key-file: 自动为 kubelet 颁发证书的 CA, 与 apiserver 保持一致
2. systemd 管理 controller-manager
cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure[Install]
WantedBy=multi-user.target
EOF
3.启动并设置开机启动
systemctl daemon-reload
systemctl start kube-controller-manager
systemctl enable kube-controller-manager
5.6 部署 kube-scheduler
1. 创建配置文件
cat > /opt/kubernetes/cfg/kube-scheduler.conf << EOF
KUBE_SCHEDULER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--leader-elect \
--master=127.0.0.1:8080 \
--bind-address=127.0.0.1"
EOF
– master: 通过本地非安全本地端口 8080 连接 apiserver。
– leader-elect: 当该组件启动多个时, 自动选举( HA)
2. systemd 管理 scheduler
cat > /usr/lib/systemd/system/kube-scheduler.service << EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-scheduler.conf
ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
Restart=on-failure[Install]
WantedBy=multi-user.target
EOF
3. 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-scheduler
systemctl enable kube-scheduler
4. 查看集群状态
所有组件都已经启动成功, 通过 kubectl 工具查看当前集群组件状态:
kubectl get cs
查看原因
journalctl -xe
发现controller-manage启动失败查看原因 原来是少了一个空格
修改完毕重启
再次查看
如上输出说明 Master 节点组件运行正常。
6、 安装 Docker
下载地址: https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz
以下在所有节点操作。 这里采用二进制安装, 用 yum 安装也一样 注:由于master后续需要安装kubelet,所以master也要安装docker
这里只展示node1节点的命令
肯定有小伙伴想要问为什么master没有安装docker呢?
因为Master 节点和 Worker 节点的角色不同。
在 Kubernetes 二进制方式搭建集群中,通常在 Master 节点上安装 kube-apiserver、kube-scheduler、kube-controller-manager、etcd 等组件,而不是安装 Docker。这是因为 Master 节点不会直接运行容器,它的主要职责是管理和调度容器,所以它只需要依赖于 Docker 或其他容器运行时就可以了。
( 1) 解压二进制包
解压
tar zxvf docker-19.03.9.tgz
将docker目录下的所有文件移动到/usr/bin目录下。
mv docker/* /usr/bin
( 2) systemd 管理 docker
docker.service是 Docker 服务的服务单元文件,其作用是定义 Docker 服务的启动方式、运行环境以及相关的依赖关系,使得操作系统能够在启动时正确地启动 Docker 服务。
systemd 服务管理器会自动加载这些服务单元文件,并根据其中定义的规则来管理系统服务。
cat > /usr/lib/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
( 3) 创建配置文件
Docker守护进程的配置文件,它用于配置Docker守护进程的行为和属性。
这里配置了Docker镜像仓库地址。
mkdir /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://vpmkvcwz.mirror.aliyuncs.com"]
}
EOF
registry-mirrors 阿里云镜像站点
( 4) 启动并设置开机启动
systemctl daemon-reload
systemctl start docker
systemctl enable docker
查看docker信息
docker info
[root@node1 ~]# docker info
Client:Debug Mode: falseServer:Containers: 0Running: 0Paused: 0Stopped: 0Images: 0Server Version: 19.03.9Storage Driver: overlay2Backing Filesystem: xfsSupports d_type: trueNative Overlay Diff: trueLogging Driver: json-fileCgroup Driver: cgroupfsPlugins:Volume: localNetwork: bridge host ipvlan macvlan null overlayLog: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslogSwarm: inactiveRuntimes: runcDefault Runtime: runcInit Binary: docker-initcontainerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429runc version: dc9208a3303feef5b3839f4323d9beb36df0a9ddinit version: fec3683Security Options:seccompProfile: defaultKernel Version: 3.10.0-1160.el7.x86_64Operating System: CentOS Linux 7 (Core)OSType: linuxArchitecture: x86_64CPUs: 1Total Memory: 972.3MiBName: node1ID: DUDF:D4US:NWFZ:SG2O:2QUY:UWNX:DYUH:IEG5:CG5E:F6ND:JGVK:BX34Docker Root Dir: /var/lib/dockerDebug Mode: falseRegistry: https://index.docker.io/v1/Labels:Experimental: falseInsecure Registries:127.0.0.0/8Registry Mirrors:https://vpmkvcwz.mirror.aliyuncs.com/Live Restore Enabled: falseProduct License: Community Engine
7、 部署 Worker Node
master节点也部署成worker节点,一并参加调度
并且在master进行统一配置,然后将配置拷贝到worke node中进行快速部署
7.1 创建工作目录并拷贝二进制文件
在所有 worker node 创建工作目录:
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
从 master 节点进行拷贝:
cd kubernetes/server/bin
cp kubelet kube-proxy /opt/kubernetes/bin
7.2 部署 kubelet
kubelet:每个 Node 节点上的 kubelet 定期就会调用 API Server 的 REST 接口报告自身状态,API Server 接收这些信息后,将节点状态信息更新到 etcd 中。kubelet 也通过 API Server 监听 Pod 信息,从而对 Node 机器上的 POD 进行管理,如创建、删除、更新 Pod。
即使在 master 节点上不需要直接运行容器,也可以部署 kubelet 来保证 Kubernetes 集群的正常运行。
1. 创建配置文件
cat > /opt/kubernetes/cfg/kubelet.conf << EOF
KUBELET_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=master \\
--network-plugin=cni \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
--config=/opt/kubernetes/cfg/kubelet-config.yml \\
--cert-dir=/opt/kubernetes/ssl \\
--pod-infra-container-image=lizhenliang/pause-amd64:3.0"
EOF
–hostname-override:显示名称,集群中唯一
–network-plugin:启用 CNI
–kubeconfig:空路径,会自动生成,后面用于连接 apiserver
–bootstrap-kubeconfig:首次启动向 apiserver 申请证书
–config:配置参数文件
–cert-dir:kubelet 证书生成目录
–pod-infra-container-image:管理 Pod 网络容器的镜像
2. 配置参数文件
请注意yml格式空行
cat > /opt/kubernetes/cfg/kubelet-config.yml << EOF
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS:- 10.0.0.2
clusterDomain: cluster.local
failSwapOn: false
authentication:anonymous:enabled: falsewebhook:cacheTTL: 2m0senabled: truex509:clientCAFile: /opt/kubernetes/ssl/ca.pem
authorization:mode: Webhookwebhook:cacheAuthorizedTTL: 5m0scacheUnauthorizedTTL: 30s
evictionHard:imagefs.available: 15%memory.available: 100Minodefs.available: 10%nodefs.inodesFree: 5%
maxOpenFiles: 1000000
maxPods: 110
EOF
3. 生成 bootstrap.kubeconfig 文件
这个文件被用来创建一个kubelet-bootstrap用户来启动kubelet进程并注册到集群中
指定 Kubernetes API server 的地址和端口。
KUBE_APISERVER="https://192.168.122.143:6443" # apiserver IP:PORT
其中的token与 token.csv 里保持一致
TOKEN="c47ffb939f5ca36231d9e3121a252940"
查看token值
cat /opt/kubernetes/cfg/token.csv
生成 kubelet bootstrap kubeconfig 配置文件
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=bootstrap.kubeconfigkubectl config set-credentials "kubelet-bootstrap" \
--token=${TOKEN} \
--kubeconfig=bootstrap.kubeconfigkubectl config set-context default \
--cluster=kubernetes \
--user="kubelet-bootstrap" \
--kubeconfig=bootstrap.kubeconfigkubectl config use-context default \
--kubeconfig=bootstrap.kubeconfig
这个命令可以一起执行的,可以通过;或&&连接
拷贝到配置文件路径:
cp bootstrap.kubeconfig /opt/kubernetes/cfg
4. systemd 管理 kubelet
cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet.conf
ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
5. 启动并设置开机启动
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
报错
1.注意:kubernetes官方推荐docker等使用systemd作为Cgroup Driver,如果kubelet服务状态异常,查看日志是cgroupDriver不匹配的话,先查看docker使用的Cgroup Driver
docker info|grep “Cgroup Driver”
再修改kubelet的yaml文件中Cgroup Driver的参数
2.启动失败failed to run Kubelet: failed to get docker version: Cannot connect to the Docker daemon at unix:///var/run/docker.s
开始以为docker启动失败或者deamon.json配置有问题,经过确认后没发现问题,最终在查看systemd 管理 kubelet的kubelet.service文件中发现多了一个\
修改后
重新启动
7.3 批准 kubelet 证书申请并加入集群
每个节点部署申请后都需被批准才能加入集群
# 查看 kubelet 证书请求
kubectl get csr
# 批准申请
kubectl certificate approve node-csr-VXXOMedFY9mQu9_wh2t64wqeBXHRJL8H68DfougGySA
# 查看节点
kubectl get node
注:由于网络插件还没有部署,节点会没有准备就绪 NotReady
7.4 部署 kube-proxy
1. 创建配置文件
cat > /opt/kubernetes/cfg/kube-proxy.conf << EOF
KUBE_PROXY_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--config=/opt/kubernetes/cfg/kube-proxy-config.yml"
EOF
2. 配置参数文件
cat > /opt/kubernetes/cfg/kube-proxy-config.yml << EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
metricsBindAddress: 0.0.0.0:10249
clientConnection:kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfig
hostnameOverride: master
clusterCIDR: 10.0.0.0/24
EOF
3. 生成 kube-proxy.kubeconfig 文件
生成 kube-proxy 证书:
# 切换工作目录
cd /root/TLS/k8s
# 创建证书请求文件
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
查看
ls kube-proxy*pem
生成 kubeconfig 文件:
KUBE_APISERVER="https://192.168.122.143:6443"
kubectl config set-cluster kubernetes --certificate-authority=/opt/kubernetes/ssl/ca.pem --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=kube-proxy.kubeconfigkubectl config set-credentials kube-proxy --client-certificate=./kube-proxy.pem --client-key=./kube-proxy-key.pem --embed-certs=true --kubeconfig=kube-proxy.kubeconfigkubectl config set-context default --cluster=kubernetes --user=kube-proxy --kubeconfig=kube-proxy.kubeconfigkubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
拷贝到配置文件指定路径:
cp kube-proxy.kubeconfig /opt/kubernetes/cfg/
4. systemd 管理 kube-proxy
cat > /usr/lib/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-proxy.conf
ExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
5. 启动并设置开机启动
systemctl daemon-reload
systemctl start kube-proxy
systemctl enable kube-proxy
报错
1.提示找不到kubernetes集群invalid configuration: no server found for cluster “kubernetes”
这是因为在 生成 kubeconfig 文件时没有执行这个命令
KUBE_APISERVER="https://192.168.122.143:6443"
执行后,重新生成生成 kubeconfig 文件,重新启动kube-proxy即可
7.5 部署 CNI 网络
CNI是Container Network Interface(容器网络接口)的缩写,是一个规范,为容器运行时(如Docker、Kubernetes等)提供了一套插件化的网络配置和管理机制。CNI插件负责实现网络配置、管理和连接,其中包括IP地址分配、路由设置、网络隔离等功能,通过CNI插件,容器可以连接到不同类型的网络,如物理网络、虚拟网络、Overlay网络等等。在Kubernetes中,CNI被用作容器网络的管理接口,可以实现多种不同的网络方案,如Flannel、Calico、Cilium等。
先准备好 CNI 二进制文件:
下载地址:
https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-linux-amd64-v0.8.6.tgz
解压二进制包并移动到默认工作目录:
mkdir /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin
部署 CNI 网络:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
若默认镜像地址无法访问,修改为 docker hub 镜像仓库。
sed -i -r "s#quay.io/coreos/flannel:.*-amd64#lizhenliang/flannel:v0.12.0-amd64#g" kube-flannel.yml
启动
kubectl apply -f kube-flannel.yml
kubectl get node
部署好网络插件,Node 准备就绪
kubectl get pods -n kube-system
这里获取不到pod是因为node节点还没开始部署,先跳过
7.6 授权 apiserver 访问 kubelet
cat > apiserver-to-kubelet-rbac.yaml<< EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:annotations:rbac.authorization.kubernetes.io/autoupdate: "true"labels:kubernetes.io/bootstrapping: rbac-defaultsname: system:kube-apiserver-to-kubelet
rules:
- apiGroups:- ""resources:- nodes/proxy- nodes/stats- nodes/log- nodes/spec- nodes/metrics- pods/logverbs:- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: system:kube-apiservernamespace: ""
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: system:kube-apiserver-to-kubelet
subjects:
- apiGroup: rbac.authorization.k8s.iokind: Username: kubernetes
EOF
授权访问kubelet
kubectl apply -f apiserver-to-kubelet-rbac.yaml
查看
kubectl get ClusterRole
7.7 新增加 Worker Node
这里才真正到部署Worker Node操作
1. 在mster中****拷贝已部署好的 Node 相关文件到新节点
在 master 节点将 Worker Node 涉及文件拷贝到节点 192.168.122.144 、192.168.122.145
这里只展示node1节点的操作
scp -r /opt/kubernetes root@192.168.122.144:/opt/
scp -r /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@192.168.122.144:/usr/lib/systemd/system
scp -r /opt/cni/ root@192.168.122.144:/opt/
scp /opt/kubernetes/ssl/ca.pem root@192.168.122.144:/opt/kubernetes/ssl
2. 删除node节点的 kubelet 证书和 kubeconfig 文件
rm /opt/kubernetes/cfg/kubelet.kubeconfig
rm -f /opt/kubernetes/ssl/kubelet*
注:这几个文件是证书申请审批后自动生成的,每个 Node 不同,必须删除重新生成。否则master节点无法获得node节点信息
3. 修改主机名
vi /opt/kubernetes/cfg/kubelet.conf
修改主机名
--hostname-override=node1
vi /opt/kubernetes/cfg/kube-proxy-config.yml
修改主机名
hostnameOverride: node1
4. 启动并设置开机启动
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
systemctl start kube-proxy
systemctl enable kube-proxy
报错
1.查看状态发现kubectl启动失败
查看具体问题 使用 journalctl -xe命令
想到应该是节点没有启动docker
重新启动,ok
这里要注意也要设置镜像加速器地址
5. 在 Master 上批准新 Node kubelet 证书申请
查看证书请求
kubectl get csr
授权请求
kubectl certificate approve node-csr-TI8Mrdx61UpWpuPJswDzUngNjivBM5rMw4qZbfTT6PA
6. 查看 Node 状态
kubectl get node
Node2(192.168.122.145 )节点同上。记得修改主机名!
继续部署node2配合,操作同上
8、测试kubernetes集群
在 Kubernetes 集群中创建一个 pod,验证是否正常运行【master 节点操作】
8.1下载 nginx 【会联网拉取 nginx 镜像】
kubectl create deployment nginx --image=nginx
查看状态
kubectl get pod
如果我们出现 Running 状态的时候,表示已经成功运行了
8.2下面我们就需要将端口暴露出去,让其它外界能够访问
暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort
查看一下对外的端口
kubectl get pods,svc
能够看到,我们已经成功暴露了 80 端口 到 31167 上
我们到我们的宿主机浏览器上,访问如下地址 192.168.122.143:31167
发现我们的 nginx 已经成功启动了
删除
kubectl delete deployment nginx
从Kubernetes集群中删除名为“nginx”的deployment以及相关的pod和副本集。