搭建kubernetes集群最大的麻烦其实不在于其复杂度(相对Openstack集群)而在于有GFW, 所以为了避免墙带来的麻烦, 也为了加深对kubernetes的理解, 这里将使用纯手工离线的方式进行部署(相应的文件我已经下载到百度云盘里面)。
环境介绍
下面Kubernetes集群搭建需要的版本信息:
软件 | 版本 |
---|---|
OS | CentOS Linux release 7.3.1611 (Core) |
Kubernetes | 1.8.7 |
Docker | 18.01.0-ce |
Etcd | 3.2.7 |
我们将在四台CentOS系统的物理机上部署一个4个节点的kubernetes1.8.7集群(截止当前2018.1是最新版本):
IP | Role | CPU | Memory |
---|---|---|---|
192.168.204.3 | master/node | 2核 | 4G |
192.168.204.4 | node | 2核 | 4G |
192.168.204.6 | node | 2核 | 4G |
192.168.204.7 | node | 2核 | 4G |
这里master节点同时充当node节点, 因为后面一些在部署calico网络时采用的是daemonSet, 这样才能保证master和node节点内部网络通畅。
镜像准备
在进行集群搭建时, 由于很多镜像都需要翻墙下载, 因此请先准备一个私有仓库, 关于私有仓库的搭建请参考: {% post_link harbor %}, 如果还没搭建的请搭建然后继续.
在后面的安装过程中需要依赖一个基础镜像: pause, 它是根POD镜像, 用于管理POD的网络, 存储等一些共享资源:
gcr.io/google_containers/pause-amd64:3.0
如果自己能翻墙就自己下载后推送到自己的私有仓库, 如果自己翻不了墙, 我已帮忙下载, 请到国内kubernetes镜像tar包
docker load < pause-amd64.tar
docker tag gcr.io/google_containers/pause-amd64:3.0 {PRIVATE_REGISTRIY_ADDR}/{PROJECT}/pause-amd64:3.0
docker push {PRIVATE_REGISTRIY_ADDR}/{PROJECT}/pause-amd64:3.0
集群准备
在开始搭建集群前需要做一些基础准备:
同步集群的时间
理论上systemd系统都自带了时间同步和管理的工具, 使用timedatectl命令确认下, 确保NTP synchronized为yes:
[root@k8s-apiserver ~]# timedatectl
Local time: 六 2018-01-20 02:47:59 EST
Universal time: 六 2018-01-20 07:47:59 UTC
RTC time: 六 2018-01-20 07:47:59
Time zone: America/New_York (EST, -0500)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: no
Last DST change: DST ended at
日 2017-11-05 01:59:59 EDT
日 2017-11-05 01:00:00 EST
Next DST change: DST begins (the clock jumps one hour forward) at
日 2018-03-11 01:59:59 EST
日 2018-03-11 03:00:00 EDT
关闭SELinux
SELinux是系统上的沙盒机制, 为了尽快搭建出集群, 先关闭, 如果强调高安全, 可以等集群搭建成功后开启
# 确认SELinux的配置, 如果不是disabled, 请设置成disabled, 然后从启系统
[root@k8s-apiserver ~]# cat /etc/selinux/config | grep ^SELINUX=
SELINUX=disabled
# 查看当前SELinux是否已经成功关闭
[root@k8s-apiserver ~]# getenforce
Disabled
关闭防火墙(搭建成功后可以慢慢开启)
systemd系统一般都采用firewalld作为防火墙, 同理如果没关闭 先关闭
[root@k8s-apiserver ~]# systemctl is-enabled firewalld
disabled
# 如果未关闭请执行
[root@k8s-apiserver ~]# systemctl stop firewalld
[root@k8s-apiserver ~]# systemctl disable firewalld
[root@k8s-apiserver ~]# systemctl is-enabled firewalld
disabled
集群部署
接下来进入集群的部署阶段, 部署分为如下几个阶段:
- CA和证书准备
- 部署kubernetes客户端工具kubectl
- node节点的TLS证书引导(TLS Bootstrap)配置准备
- 部署ETCD
- 部署master节点
- 部署node节点
- 集群测试
在进入部署之前, 先看看kubernetes组件的架构:
Kubernetes主要由以下几个核心组件组成:
- etcd保存了整个集群的状态;
- apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
- controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
- scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
- kubelet负责维持容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
- Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
- kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;
CA和证书准备
kubernetes是一套分布式系统, 系统的各组件均使用TLS来进行身份的双向确认和通信加密, 本文档使用CloudFlare提供的PKI工具集 cfssl来生成Certificate Authority (CA)和管理证书(openssl已可以, 但是你需要一步一步的填写).
我们需要为每一个kubernetes的组件生成证书, 总结起来如下:
- kubectl: 用户的CLI工具, 需要为用户生成访问的证书, 这里需要为admin用户颁发1张证书
- master: apiserver, controller manager, scheduler, etcd 这4个服务都在master节点上, 因此为他们颁发1张证书
- node: kubelet, kube-proxy 由于kubelet的证书是动态颁发的(TLS Bootstra), 因此这里仅需要为kube-proxy颁发1张证书
安装cfssl工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
chmod +x cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
创建CA
首先我们创建一个目录pki, 后面的操作都在这个目录里面进行
mkdir pki && cd pki
首先创建CA的配置文件: ca-config.json
# 过期时间设置成了 87600h
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF
关于CA配置文件里面的参数说明:
- ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
- signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
- server auth:表示client可以用该 CA 对server提供的证书进行验证;
- client auth:表示server可以用该CA对client提供的证书进行验证;
创建CA证书签名请求
cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
关于证书签名请求的参数说明:
- “CN”:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
- “O”:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
生成CA证书和私钥
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
$ ls ca*
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
admin用户证书
后续kube-apiserver使用RBAC对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
kube-apiserver 预定义了一些RBAC使用的RoleBindings, 如cluster-admin将Group system:masters与Role cluster-admin 绑定,该Role授予了调用kube-apiserver的所有API的权限, 意思是凡是system:masters Group的user都拥有cluster-admin的角色。 因此我们在使用kubectl命令时候,才拥有整个集群的管理权限(后面部署了客户端工具方可查看);
因此admin用户证书申请的核心是指定Group: Group system:masters, 这样该用户就有访问APIServer的所有权限的.
签名请求参数如下:
cat > admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "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
$ ls admin*
admin.csr admin-csr.json admin-key.pem admin.pem
master服务证书
cat > kubernetes-csr.json <<EOF
{