使用二进制的方式部署 K8S-1.16 高可用集群(二十)
一、项目介绍
项目致力于让有意向使用原生kubernetes集群的企业或个人,可以方便的、系统的使用二进制的方式手工搭建kubernetes高可用集群。并且让相关的人员可以更好的理解kubernetes集群的运作机制。
软件版本
- os centos7.7(ubuntu也适用,需要替换部分命令)
- kubernetes 1.16.2
- etcd 3.4.3
- docker 18.06
- calico 3.10.1-2
- coredns
配置策略
kube-apiserver:
- 使用节点本地 nginx 4 层透明代理实现高可用;
- 关闭非安全端口 8080 和匿名访问;
- 在安全端口 6443 接收 https 请求;
- 严格的认证和授权策略 (x509、token、RBAC);
- 开启 bootstrap token 认证,支持 kubelet TLS bootstrapping;
- 使用 https 访问 kubelet、etcd,加密通信;
kube-controller-manager:
- 3 节点高可用;
- 关闭非安全端口 10252,在安全端口 10257 接收 https 请求;
- 使用 kubeconfig 访问 apiserver 的安全端口;
- 自动 approve kubelet 证书签名请求 (CSR),证书过期后自动轮转;
- 各 controller 使用自己的 ServiceAccount 访问 apiserver;
kube-scheduler:
- 3 节点高可用;
- 关闭非安全端口 10251,在安全端口 10259 接收 https 请求;
- 使用 kubeconfig 访问 apiserver 的安全端口;
kubelet:
- 使用 kubeadm 动态创建 bootstrap token,而不是在 apiserver 中静态配置;
- 使用 TLS bootstrap 机制自动生成 client 和 server 证书,过期后自动轮转;
- 在 KubeletConfiguration 类型的 JSON 文件配置主要参数;
- 关闭只读端口 10255,在安全端口 10250 接收 https 请求,对请求进行认证和授权,拒绝匿名访问和非授权访问;
- 使用 kubeconfig 访问 apiserver 的安全端口;
kube-proxy:
- 使用 kubeconfig 访问 apiserver 的安全端口;
- 在 KubeProxyConfiguration 类型的 JSON 文件配置主要参数;
- 使用 ipvs 代理模式;
集群插件:
- DNS:使用功能、性能更好的 coredns;
- Dashboard:支持登录认证;
- Metric:metrics-server,使用 https 访问 kubelet 安全端口;
- Log:Elasticsearch、Fluend、Kibana;
- Registry 镜像库:docker-registry、harbor;
二、实践环境准备
1. 服务器说明
我们这里使用的是五台centos 7.7虚拟机,具体信息如下表:
系统类型 | IP地址 | 节点角色 | CPU | Memory | Hostname |
---|---|---|---|---|---|
centos-7.7 | 172.18.0.100 | master | >=2 | >=2G | k8s-m01 |
centos-7.7 | 172.18.0.101 | master | >=2 | >=2G | k8s-m02 |
centos-7.7 | 172.18.0.102 | master | >=2 | >=2G | k8s-m03 |
centos-7.7 | 172.18.0.103 | worker | >=2 | >=2G | k8s-n01 |
centos-7.7 | 172.18.0.104 | worker | >=2 | >=2G | k8s-n02 |
2. 系统设置(所有节点)
2.1 主机名
主机名必须每个节点都不一样,并且保证所有点之间可以通过 hostname 互相访问。
# 查看主机名$ hostname# 修改主机名$ hostnamectl set-hostname # 配置host,使主节点之间可以通过hostname互相访问$ vi /etc/hosts#
2.2 安装依赖包
# 更新yum$ yum update# 安装依赖包$ yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp wget## 时间同步$ ntpdate time1.aliyun.com
2.3 关闭防火墙、swap,重置iptables
# 关闭防火墙$ systemctl stop firewalld && systemctl disable firewalld# 重置iptables$ iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT# 关闭swap$ swapoff -a$ sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab# 关闭selinux$ setenforce 0# 关闭dnsmasq(否则可能导致docker容器无法解析域名)$ service dnsmasq stop && systemctl disable dnsmasq
2.4 系统参数设置
# 制作配置文件$ cat > /etc/sysctl.d/kubernetes.conf <
2.5 加载内核模块
modprobe ip_vs_rrmodprobe br_netfilter
3. 安装docker(worker节点)
根据kubernetes对docker版本的兼容测试情况,我们选择18.06版本,我们配置阿里云的源,速度比较快。
# 添加 yum 源wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -P /etc/yum.repos.d/# 清理原有版本yum remove -y docker* container-selinux# 安装dockeryum list docker-ce.x86_64 --showduplicates |sort -ryum install docker-ce-18.06.1.ce -y# 开机启动systemctl enable docker# 配置加速器sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{ "registry-mirrors": ["https://hdi5v8p1.mirror.aliyuncs.com"]}EOF# 启动docker服务service docker restart
4. 准备二进制文件(所有节点)
4.1 配置免密登录
为了方便文件的copy我们选择一个中转节点(随便一个节点,可以是集群中的也可以是非集群中的),配置好跟其他所有节点的免密登录,我们这里使用 k8s-m01。
# 看看是否已经存在rsa公钥$ cat ~/.ssh/id_rsa.pub# 如果不存在就创建一个新的$ ssh-keygen -t rsa# 免密钥认证$ ssh-copy-id root@
4.2 下载二进制文件
官方下载地址(在CHANGELOG链接里面):
https://github.com/kubernetes/kubernetes/releases
我们选择的版本是 1.16.2
。
网盘下载地址--推荐(我从官网下载整理好的文件):
链接: https://pan.baidu.com/s/1Ut9VERgm55B4lmz0wjjzFQ
提取码: mjem
4.3 分发文件
# 把文件copy到每个节点上(注意替换自己的文件目录)$ scp master/* @:/usr/local/bin/$ scp worker/* @:/usr/local/bin/# 给文件添加可执行权限$ chmod +x /usr/local/bin/*
5. 准备配置文件(k8s-m01 节点)
上一步我们下载了kubernetes各个组件的二进制文件,这些可执行文件的运行也是需要添加很多参数的,包括有的还会依赖一些配置文件。现在我们就把运行它们需要的参数和配置文件都准备好。
5.1 下载配置文件
我这准备了一个项目,专门为大家按照自己的环境生成配置的。它只是帮助大家尽量的减少了机械化的重复工作。它并不会帮你设置系统环境,不会给你安装软件。总之就是会减少你的部署工作量,但不会耽误你对整个系统的认识和把控。
$ cd ~$ git clone https://github.com/wangzan18/kubernetes-ha-binary.git# 看看git内容$ ls -l kubernetes-ha-binaryaddons/configs/pki/services/init.shglobal-configs.properties
5.2 文件说明
addons :kubernetes的插件目录,包括calico、coredns、dashboard等。
configs:这个目录比较 - 凌乱,包含了部署集群过程中用到的杂七杂八的配置文件、脚本文件等。
pki:各个组件的认证授权相关证书配置。
services:所有的kubernetes服务(service)配置文件。
global-configs.properties:全局配置,包含各种易变的配置内容。
init.sh:初始化脚本,配置好global-config之后,会自动生成所有配置文件。
5.3 生成配置
这里会根据大家各自的环境生成kubernetes部署过程需要的配置文件。
在每个节点上都生成一遍,把所有配置都生成好,后面会根据节点类型去使用相关的配置。
# cd到之前下载的git代码目录$ cd kubernetes-ha-binary# 编辑属性配置(根据文件注释中的说明填写好每个key-value)$ vim global-config.properties# 生成配置文件,确保执行过程没有异常信息$ ./init.sh# 查看生成的配置文件,确保脚本执行成功$ find target/ -type f
三、高可用集群部署
1. CA证书(任意节点)
1.1 安装cfssl
cfssl是非常好用的CA工具,我们用它来生成证书和秘钥文件
安装过程比较简单,如下:
# 下载$ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl$ wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson# 修改为可执行权限$ chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson# 验证$ cfssl versionVersion: 1.2.0Revision: devRuntime: go1.6
1.2 生成根证书
查看证书配置文件,CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等),后续在签名其它证书时需要指定特定场景。
$ cd target/pki/$ cat ca-config.json{ "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } }}
signing
:表示该证书可用于签名其它证书,生成的ca.pem
证书中CA=TRUE
;server auth
:表示 client 可以用该该证书对 server 提供的证书进行验证;client auth
:表示 server 可以用该该证书对 client 提供的证书进行验证;
查看证书签名请求文件。
$ cat ca-csr.json { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "seven" } ]}
- CN:
Common Name
,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name),浏览器使用该字段验证网站是否合法; - O:
Organization
,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group); - kube-apiserver 将提取的 User、Group 作为
RBAC
授权的用户标识;
根证书是集群所有节点共享的,只需要创建一个 CA 证书,后续创建的所有证书都由它签名。
# 生成证书和私钥$ cd target/pki$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca# 生成完成后会有以下文件(我们最终想要的就是ca-key.pem和ca.pem,一个秘钥,一个证书)$ lsca-config.json ca.csr ca-csr.json ca-key.pem ca.pem# 创建目录$ ssh @ "mkdir -p /etc/kubernetes/pki/"# 分发到每个matser主节点$ scp ca*.pem @:/etc/kubernetes/pki/
2. 部署etcd集群(master节点)
2.1 下载etcd,并传到各master节点
$ wget https://github.com/etcd-io/etcd/releases/download/v3.4.3/etcd-v3.4.3-linux-amd64.tar.gz$ tar xf etcd-v3.4.3-linux-amd64.tar.gz$ scp etcd-v3.4.3-linux-amd64/etcd* @:/usr/local/bin/
2.2 生成证书和私钥
查看证书请求文件。
$ cd target/pki/etcd$ cat etcd-csr.json{ "CN": "etcd", "hosts": [ "127.0.0.1", "172.18.0.100", "172.18.0.101", "172.18.0.102" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "seven" } ]}
- hosts 字段指定授权使用该证书的 etcd 节点 IP 或域名列表,需要将 etcd 集群的三个节点 IP 都列在其中;
# 生成证书、私钥$ cfssl gencert -ca=../ca.pem \ -ca-key=../ca-key.pem \ -config=../ca-config.json \ -profile=kubernetes etcd-csr.json | cfssljson -bare etcd# 分发到每个etcd节点(master节点)$ scp etcd*.pem @:/etc/kubernetes/pki/
2.3 创建service文件
# scp配置文件到每个master节点$ scp target//services/etcd.service :/etc/systemd/system/# 创建数据和工作目录$ ssh @ "mkdir -p /var/lib/etcd"
2.4 启动服务
etcd 进程首次启动时会等待其它节点的 etcd 加入集群,命令 systemctl start etcd 会卡住一段时间,为正常现象。
#启动服务$ systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd#查看状态$ service etcd status#查看启动日志$ journalctl -f -u etcd#查看服务监听端口$ netstat -tlnp |grep etcd
3. 部署api-server(master节点)
3.1 生成证书和私钥
查看证书请求文件。
$ cd target/pki/apiserver$ cat kubernetes-csr.json { "CN": "kubernetes", "hosts": [ "127.0.0.1", "172.18.0.100", "172.18.0.101", "172.18.0.102", "172.18.0.88", "10.96.0.1", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "seven" } ]}
# 生成证书、私钥$ cfssl gencert -ca=../ca.pem \ -ca-key=../ca-key.pem \ -config=../ca-config.json \ -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes# 分发到每个master节点$ scp kubernetes*.pem @:/etc/kubernetes/pki/
3.2 创建后续访问 metrics-server 使用的证书
创建证书签名请求:
$ cd target/pki/metrics-server$ cat > proxy-client-csr.json <
- CN 名称需要位于 kube-apiserver 的
--requestheader-allowed-names
参数中,否则后续访问 metrics 时会提示权限不足。
生成证书和私钥:
$ cfssl gencert -ca=../ca.pem \ -ca-key=../ca-key.pem \ -config=../ca-config.json \ -profile=kubernetes proxy-client-csr.json | cfssljson -bare proxy-client# 分发到每个master节点$ scp proxy-client*.pem @:/etc/kubernetes/pki/
3.3 创建service文件
# scp配置文件到每个master节点$ scp target//services/kube-apiserver.service @:/etc/systemd/system/# 创建日志目录$ ssh @ "mkdir -p /var/log/kubernetes"# 复制配置文件$ scp target/configs/encryption-config.yaml @:/etc/kubernetes/$ scp target/configs/audit-policy.yaml @:/etc/kubernetes/
3.3 启动服务
#启动服务$ systemctl daemon-reload && systemctl enable kube-apiserver && systemctl restart kube-apiserver#查看运行状态$ service kube-apiserver status#查看日志$ journalctl -f -u kube-apiserver#检查监听端口$ netstat -ntlp|grep kube-apiserver
4. 部署keepalived - apiserver高可用(master节点)
可以使用 nginx 做负载均衡器,把请求分发到后面三台apiserver服务器上面,这样最好,也是官方推荐的。
4.1 安装keepalived
# 在两个主节点上安装keepalived(一主一备),我这里选择 k8s-m01, k8s-m02$ yum install -y keepalived
4.2 创建keepalived配置文件
# 创建目录$ ssh @ "mkdir -p /etc/keepalived"$ ssh @ "mkdir -p /etc/keepalived"# 分发配置文件$ scp target/configs/keepalived-master.conf @:/etc/keepalived/keepalived.conf$ scp target/configs/keepalived-backup.conf @:/etc/keepalived/keepalived.conf# 分发监测脚本$ scp target/configs/check-apiserver.sh @:/etc/keepalived/$ scp target/configs/check-apiserver.sh @:/etc/keepalived/
4.3 启动keepalived
# 分别在master和backup上启动服务$ systemctl enable keepalived && service keepalived start# 检查状态$ service keepalived status# 查看日志$ journalctl -f -u keepalived# 访问测试$ curl --insecure https://:6443/{ "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401}
5. 部署kubectl(任意节点),我选择 k8s-m01
kubectl 是 kubernetes 集群的命令行管理工具,它默认从 ~/.kube/config 文件读取 kube-apiserver 地址、证书、用户名等信息。
5.1 创建 admin 证书和私钥
kubectl 与 apiserver https 安全端口通信,apiserver 对提供的证书进行认证和授权。
kubectl 作为集群的管理工具,需要被授予最高权限。这里创建具有最高权限的 admin 证书。
$ cd target/pki/admin$ cat admin-csr.json { "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:masters", "OU": "seven" } ]}
- O 为
system:masters
,kube-apiserver 收到该证书后将请求的 Group 设置为 system:masters; - 预定义的 ClusterRoleBinding
cluster-admin
将 Groupsystem:masters
与 Rolecluster-admin
绑定,该 Role 授予所有 API的权限; - 该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;
# 创建证书、私钥$ cfssl gencert -ca=../ca.pem \ -ca-key=../ca-key.pem \ -config=../ca-config.json \ -profile=kubernetes admin-csr.json | cfssljson -bare admin
5.2 创建kubeconfig配置文件
kubeconfig 为 kubectl 的配置文件,包含访问 apiserver 的所有信息,如 apiserver 地址、CA 证书和自身使用的证书
# 设置集群参数$ kubectl config set-cluster kubernetes \ --certificate-authority=../ca.pem \ --embed-certs=true \ --server=https://:6443 \ --kubeconfig=kube.config# 设置客户端认证参数$ kubectl config set-credentials admin \ --client-certificate=admin.pem \ --client-key=admin-key.pem \ --embed-certs=true \ --kubeconfig=kube.config# 设置上下文参数$ kubectl config set-context admin@kubernetes \ --cluster=kubernetes \ --user=admin \ --kubeconfig=kube.config# 设置默认上下文$ kubectl config use-context admin@kubernetes --kubeconfig=kube.config# 分发到目标节点$ scp kube.config @:~/.kube/config
--certificate-authority
:验证 kube-apiserver 证书的根证书;--client-certificate
、--client-key
:刚生成的admin
证书和私钥,连接 kube-apiserver 时使用;--embed-certs=true
:将 ca.pem 和 admin.pem 证书内容嵌入到生成的 kubectl.kubeconfig 文件中(不加时,写入的是证书文件路径,后续拷贝 kubeconfig 到其它机器时,还需要单独拷贝证书文件,不方便。);
5.3 授予 kubernetes 证书访问 kubelet API 的权限
在执行 kubectl exec、run、logs 等命令时,apiserver 会转发到 kubelet。这里定义 RBAC 规则,授权 apiserver 调用 kubelet API。
$ kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes
5.4 小测试
# 查看集群信息$ kubectl cluster-info$ kubectl get all -A$ kubectl get cs
6. 部署controller-manager(master节点)
controller-manager启动后将通过竞争选举机制产生一个 leader 节点,其它节点为阻塞状态。当 leader 节点不可用后,剩余节点将再次进行选举产生新的 leader 节点,从而保证服务的可用性。
6.1 创建证书和私钥
查看证书请求。
$ cd target/pki/controller-manager$ cat controller-manager-csr.json { "CN": "system:kube-controller-manager", "key": { "algo": "rsa", "size": 2048 }, "hosts": [ "127.0.0.1", "172.18.0.100", "172.18.0.101", "172.18.0.102" ], "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:kube-controller-manager", "OU": "seven" } ]}
- hosts 列表包含所有 kube-controller-manager 节点 IP;
- CN 和 O 均为
system:kube-controller-manager
,kubernetes 内置的 ClusterRoleBindingssystem:kube-controller-manager
赋予 kube-controller-manager 工作所需的权限。
# 生成证书、私钥$ cfssl gencert -ca=../ca.pem \ -ca-key=../ca-key.pem \ -config=../ca-config.json \ -profile=kubernetes controller-manager-csr.json | cfssljson -bare controller-manager# 分发到每个master节点$ scp controller-manager*.pem @:/etc/kubernetes/pki/
6.2 创建controller-manager的kubeconfig
# 创建kubeconfig$ kubectl config set-cluster kubernetes \ --certificate-authority=../ca.pem \ --embed-certs=true \ --server=https://:6443 \ --kubeconfig=controller-manager.kubeconfig$ kubectl config set-credentials system:kube-controller-manager \ --client-certificate=controller-manager.pem \ --client-key=controller-manager-key.pem \ --embed-certs=true \ --kubeconfig=controller-manager.kubeconfig$ kubectl config set-context system:kube-controller-manager@kubernetes \ --cluster=kubernetes \ --user=system:kube-controller-manager \ --kubeconfig=controller-manager.kubeconfig$ kubectl config use-context system:kube-controller-manager@kubernetes --kubeconfig=controller-manager.kubeconfig# 分发controller-manager.kubeconfig$ scp controller-manager.kubeconfig @:/etc/kubernetes/
6.3 创建service文件
# scp配置文件到每个master节点$ scp target//services/kube-controller-manager.service @:/etc/systemd/system/
6.4 启动服务
# 启动服务$ systemctl daemon-reload && systemctl enable kube-controller-manager && systemctl restart kube-controller-manager# 检查状态$ service kube-controller-manager status# 查看日志$ journalctl -f -u kube-controller-manager# 查看leader$ kubectl get endpoints kube-controller-manager --namespace=kube-system -o yaml
7. 部署scheduler(master节点)
scheduler启动后将通过竞争选举机制产生一个 leader 节点,其它节点为阻塞状态。当 leader 节点不可用后,剩余节点将再次进行选举产生新的 leader 节点,从而保证服务的可用性。
7.1 创建证书和私钥
查看证书请求文件。
$ cd target/pki/scheduler$ cat scheduler-csr.json { "CN": "system:kube-scheduler", "hosts": [ "127.0.0.1", "172.18.0.100", "172.18.0.101", "172.18.0.102" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:kube-scheduler", "OU": "seven" } ]}
- hosts 列表包含所有 kube-scheduler 节点 IP;
- CN 和 O 均为
system:kube-scheduler
,kubernetes 内置的 ClusterRoleBindingssystem:kube-scheduler
将赋予 kube-scheduler 工作所需的权限;
# 生成证书、私钥$ cfssl gencert -ca=../ca.pem \ -ca-key=../ca-key.pem \ -config=../ca-config.json \ -profile=kubernetes scheduler-csr.json | cfssljson -bare kube-scheduler# 分发到每个master节点$ scp kube-scheduler*.pem @:/etc/kubernetes/pki/
7.2 创建scheduler的kubeconfig
# 创建kubeconfig$ kubectl config set-cluster kubernetes \ --certificate-authority=../ca.pem \ --embed-certs=true \ --server=https://:6443 \ --kubeconfig=kube-scheduler.kubeconfig$ kubectl config set-credentials system:kube-scheduler \ --client-certificate=kube-scheduler.pem \ --client-key=kube-scheduler-key.pem \ --embed-certs=true \ --kubeconfig=kube-scheduler.kubeconfig$ kubectl config set-context system:kube-scheduler@kubernetes \ --cluster=kubernetes \ --user=system:kube-scheduler \ --kubeconfig=kube-scheduler.kubeconfig$ kubectl config use-context system:kube-scheduler@kubernetes --kubeconfig=kube-scheduler.kubeconfig# 分发kubeconfig$ scp kube-scheduler.kubeconfig @:/etc/kubernetes/
7.3 创建service文件
# scp配置文件到每个master节点$ scp target//services/kube-scheduler.service @:/etc/systemd/system/$ scp target//configs/kube-scheduler.config.yaml @:/etc/kubernetes/
7.4 启动服务
# 启动服务$ systemctl daemon-reload && systemctl enable kube-scheduler && systemctl restart kube-scheduler# 检查状态$ service kube-scheduler status# 查看日志$ journalctl -f -u kube-scheduler# 查看leader$ kubectl get endpoints kube-scheduler --namespace=kube-system -o yaml
8. 部署kubelet(worker节点)
8.1 创建bootstrap配置文件
# 创建 token$ cd target/pki/admin$ export BOOTSTRAP_TOKEN=$(kubeadm token create \ --description kubelet-bootstrap-token \ --groups system:bootstrappers:worker \ --kubeconfig kube.config)# 设置集群参数$ kubectl config set-cluster kubernetes \ --certificate-authority=../ca.pem \ --embed-certs=true \ --server=https://:6443 \ --kubeconfig=kubelet-bootstrap.kubeconfig# 设置客户端认证参数$ kubectl config set-credentials kubelet-bootstrap \ --token=${BOOTSTRAP_TOKEN} \ --kubeconfig=kubelet-bootstrap.kubeconfig# 设置上下文参数$ kubectl config set-context kubelet@kubernetes \ --cluster=kubernetes \ --user=kubelet-bootstrap \ --kubeconfig=kubelet-bootstrap.kubeconfig# 设置默认上下文$ kubectl config use-context kubelet@kubernetes --kubeconfig=kubelet-bootstrap.kubeconfig# 把生成的配置copy到每个worker节点上$ scp kubelet-bootstrap.kubeconfig @:/etc/kubernetes/kubelet-bootstrap.kubeconfig# 把ca分发到每个worker节点$ scp target/pki/ca.pem @:/etc/kubernetes/pki/# 查看生成的 token$ kubeadm token list --kubeconfig ~/.kube/config
- 向 kubeconfig 写入的是 token,bootstrap 结束后 kube-controller-manager 为 kubelet 创建 client 和 server 证书;
- token 有效期为 1 天,超期后将不能再被用来 boostrap kubelet,且会被 kube-controller-manager 的 tokencleaner 清理;
- kube-apiserver 接收 kubelet 的 bootstrap token 后,将请求的 user 设置为
system:bootstrap:<Token ID>
,group 设置为system:bootstrappers
,后续将为这个 group 设置 ClusterRoleBinding;
8.2 kubelet配置文件
把kubelet配置文件分发到每个worker节点上
$ scp target/worker-/kubelet.config.json @:/etc/kubernetes/
cat kubelet.config.json { "kind": "KubeletConfiguration", "apiVersion": "kubelet.config.k8s.io/v1beta1", "authentication": { "x509": { "clientCAFile": "/etc/kubernetes/pki/ca.pem" }, "webhook": { "enabled": true, "cacheTTL": "2m0s" }, "anonymous": { "enabled": false } }, "authorization": { "mode": "Webhook", "webhook": { "cacheAuthorizedTTL": "5m0s", "cacheUnauthorizedTTL": "30s" } }, "address": "172.18.0.103", "staticPodPath": "", "port": 10250, "readOnlyPort": 10255, "cgroupDriver": "cgroupfs", "hairpinMode": "promiscuous-bridge", "serializeImagePulls": false, "featureGates": { "RotateKubeletClientCertificate": true, "RotateKubeletServerCertificate": true }, "clusterDomain": "cluster.local.", "clusterDNS": ["10.96.0.2"]}
- authentication.anonymous.enabled:设置为 false,不允许匿名访问 10250 端口;
- authentication.x509.clientCAFile:指定签名客户端证书的 CA 证书,开启 HTTPs 证书认证;
- authentication.webhook.enabled=true:开启 HTTPs bearer token 认证;
同时配置了如下授权参数:
- authroization.mode=Webhook:开启 RBAC 授权;
kubelet 收到请求后,使用 clientCAFile 对证书签名进行认证,或者查询 bearer token 是否有效。如果两者都没通过,则拒绝请求,提示 Unauthorized:
8.3 kubelet服务文件
把kubelet服务文件分发到每个worker节点上
$ scp target/worker-/kubelet.service @:/etc/systemd/system/
8.4 启动服务
kublet 启动时查找配置的 --kubeletconfig 文件是否存在,如果不存在则使用 --bootstrap-kubeconfig 向 kube-apiserver 发送证书签名请求 (CSR)。
kube-apiserver 收到 CSR 请求后,对其中的 Token 进行认证(事先使用 kubeadm 创建的 token),认证通过后将请求的 user 设置为 system:bootstrap:,group 设置为 system:bootstrappers,这就是Bootstrap Token Auth。
# bootstrap附权$ kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers# 启动服务$ mkdir -p /var/lib/kubelet$ mkdir -p /var/log/kubernetes$ systemctl daemon-reload && systemctl enable kubelet && systemctl restart kubelet# 在master上Approve bootstrap请求$ kubectl get csr$ kubectl certificate approve # 查看服务状态$ service kubelet status# 查看日志$ journalctl -f -u kubelet
- kubelet 启动后使用 --bootstrap-kubeconfig 向 kube-apiserver 发送 CSR 请求,当这个 CSR 被 approve 后,kube-controller-manager 为 kubelet 创建 TLS 客户端证书、私钥和 --kubeletconfig 文件。
- 注意:kube-controller-manager 需要配置 --cluster-signing-cert-file 和 --cluster-signing-key-file 参数,才会为 TLS Bootstrap 创建证书和私钥。
9. 部署kube-proxy(worker节点)
9.1 创建证书和私钥
查看证书请求文件。
$ cd target/pki/proxycat kube-proxy-csr.json { "CN": "system:kube-proxy", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "seven" } ]}
- CN:指定该证书的 User 为
system:kube-proxy
; - 预定义的 RoleBinding
system:node-proxier
将Usersystem:kube-proxy
与 Rolesystem:node-proxier
绑定,该 Role 授予了调用kube-apiserver
Proxy 相关 API 的权限; - 该证书只会被 kube-proxy 当做 client 证书使用,所以 hosts 字段为空;
$ cfssl gencert -ca=../ca.pem \ -ca-key=../ca-key.pem \ -config=../ca-config.json \ -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
9.2 创建和分发 kubeconfig 文件
# 创建kube-proxy.kubeconfig$ kubectl config set-cluster kubernetes \ --certificate-authority=../ca.pem \ --embed-certs=true \ --server=https://:6443 \ --kubeconfig=kube-proxy.kubeconfig$ kubectl config set-credentials kube-proxy \ --client-certificate=kube-proxy.pem \ --client-key=kube-proxy-key.pem \ --embed-certs=true \ --kubeconfig=kube-proxy.kubeconfig$ kubectl config set-context kube-proxy@kubernetes \ --cluster=kubernetes \ --user=kube-proxy \ --kubeconfig=kube-proxy.kubeconfig$ kubectl config use-context kube-proxy@kubernetes --kubeconfig=kube-proxy.kubeconfig# 分发kube-proxy.kubeconfig 到 node 节点$ scp kube-proxy.kubeconfig @:/etc/kubernetes/
9.3 分发kube-proxy.config
$ scp target/worker-/kube-proxy.config.yaml @:/etc/kubernetes/
9.4 分发kube-proxy服务文件
$ scp target/services/kube-proxy.service @:/etc/systemd/system/
9.5 启动服务
# 创建依赖目录$ mkdir -p /var/lib/kube-proxy# 启动服务$ systemctl daemon-reload && systemctl enable kube-proxy && systemctl restart kube-proxy# 查看状态$ service kube-proxy status# 查看日志$ journalctl -f -u kube-proxy
目前是 iptables 模式,使用 ipvs 模式可以修改文件 kube-proxy.config.yaml
我这里遇到的一个问题是 iptables 版本过低,如果遇到,可以编译安装使用新版本。
10. 部署CNI插件 - calico
我们使用calico官方的安装方式来部署。
# 创建目录(在配置了kubectl的节点上执行)$ mkdir -p /etc/kubernetes/addons# 上传calico配置到配置好kubectl的节点(一个节点即可)$ scp target/addons/calico.yaml @:/etc/kubernetes/addons/# 部署calico$ kubectl apply -f /etc/kubernetes/addons/calico.yaml# 查看状态$ kubectl get pods -n kube-system
https://docs.projectcalico.org/v3.10/getting-started/kubernetes/
11. 部署DNS插件 - coredns
# 上传配置文件$ scp target/addons/coredns.yaml @:/etc/kubernetes/addons/# 部署coredns$ kubectl apply -f /etc/kubernetes/addons/coredns.yaml
https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base
四、集群可用性测试
1. 创建nginx ds
# 写入配置$ cat > nginx-ds.yml <
2. 检查各种ip连通性
# 检查各 Node 上的 Pod IP 连通性(主节点没有calico所以不能访问podip)$ kubectl get pods -o wide# 在每个worker节点上ping pod ip$ ping # 检查service可达性$ kubectl get svc# 在每个worker节点上访问服务(主节点没有proxy所以不能访问service-ip)$ curl :# 在每个节点检查node-port可用性$ curl :
3. 检查dns可用性
# 创建一个nginx pod$ cat > pod-nginx.yaml <
五. 部署dashboard
1. 部署dashboard
# 上传dashboard配置$ scp target/addons/dashboard-all.yaml @:/etc/kubernetes/addons/# 创建服务$ kubectl apply -f /etc/kubernetes/addons/dashboard-all.yaml# 查看服务运行情况$ kubectl get deployment kubernetes-dashboard -n kube-system$ kubectl --namespace kube-system get pods -o wide$ kubectl get services kubernetes-dashboard -n kube-system$ netstat -ntlp|grep 8401
2. 访问dashboard
为了集群安全,从 1.7 开始,dashboard 只允许通过 https访问,我们使用nodeport的方式暴露服务,可以使用 https://NodeIP:NodePort 地址访问。
关于自定义证书
默认dashboard的证书是自动生成的,肯定是非安全的证书,如果大家有域名和对应的安全证书可以自己替换掉。使用安全的域名方式访问dashboard。
在dashboard-all.yaml中增加dashboard启动参数,可以指定证书文件,其中证书文件是通过secret注进来的。
--tls-cert-file=dashboard.cer --tls-key-file=dashboard.key
3. 登录dashboard
Dashboard 默认只支持 token 认证,所以如果使用 KubeConfig 文件,需要在该文件中指定 token,我们这里使用token的方式登录
# 创建service account$ kubectl create sa dashboard-admin -n kube-system# 创建角色绑定关系$ kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin# 查看dashboard-admin的secret名字$ ADMIN_SECRET=$(kubectl get secrets -n kube-system | grep dashboard-admin | awk '{print $1}')# 打印secret的token$ kubectl describe secret -n kube-system ${ADMIN_SECRET} | grep -E '^token' | awk '{print $2}'
六、部署 metrics-server
metrics-server 通过 kube-apiserver 发现所有节点,然后调用 kubelet APIs(通过 https 接口)获得各节点(Node)和 Pod 的 CPU、Memory 等资源使用情况。
从 Kubernetes 1.12 开始,kubernetes 的安装脚本移除了 Heapster,从 1.13 开始完全移除了对 Heapster 的支持,Heapster 不再被维护。
1. 安装 metrics-server
$ cd target/addons$ git clone https://github.com/kubernetes-incubator/metrics-server.git$ cd metrics-server/deploy/1.8+/
修改metrics-server-deployment.yaml
文件,把 metrics-server 修改为如下命令行参数:
containers: - name: metrics-server image: wangzan18/metrics-server-amd64:v0.3.6 args: - --cert-dir=/tmp - --secure-port=4443 - --metric-resolution=30s - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
- --metric-resolution=30s:从 kubelet 采集数据的周期;
- --kubelet-preferred-address-types:优先使用 InternalIP 来访问 kubelet,这样可以避免节点名称没有 DNS 解析记录时,通过节点名称调用节点 kubelet API 失败的情况(未配置时默认的情况);
2. 部署
$ cd target/addons/metrics-server/deploy/1.8+/$ kubectl apply -f .
参考文档:https://k8s-install.opsnull.com/