开始正式k8s的航程,因为k8的坑很多,特别是因为更新移植等时候情况复杂,所以会尽可能细致的把点讲到,不会略过,方便以后的人有完整的参考,而不是支离破碎的找google. 注: kubernetes 是k8s的全称. 可以理解为舵手 or 船长吧 kubenetes读音,应为
koob-er-ne-tees
0x00. 前身
k8s前身是google内部十年经验大成的Borgs平台. 目前docker已经宣布下一代原生内置k8,k8的占有率也已经在三大编排工具占有77%的绝对优势. 所以已经势不可挡了. (其他的历史有空再说吧,因为上手过程的坑实在是太多了,不同版本的组件,不同的网络,不同的证书,以及各种内核跟不同教程的不完整性….参考了最少40篇blog+书).
最后实现的目标大致图: (后期已更新,这个是大规模生产使用,小团队无需效仿)
参考文章:
0x01.安装
首先,由于启用了 TLS 双向认证、 RBAC 授权等严格的安全机制,建议从头开始顺序部署,否则可能会认证、授权等失败.
其次,因为google源的问题,k8s大量的安装依赖以及库更新都需要break wall,这显然在普通生产环境是不可接受的. 常见三种安装方式:
- 配置yum源后,使用yum安装,好处是简单,坏处也很明显,需要google更新yum源才能获得最新版本的软件,而所有软件的依赖又不能自己指定,尤其是你的操作系统版本如果低的话,使用yum源安装的kubernetes的版本也会受到限制(不推荐,装的是1.5版本的…)。
- 使用二进制文件安装,好处是可以安装任意版本的kubernetes,坏处是配置比较复杂。
- 赶上了社区出的开源快速安装工具kubeadm(为了避免安装1万个matlab的耗时)采用集群化模式尝试打包离线安装. (缺点是不可直接用于生产环境.上线易报错.)
部署方案选取一主二节点方式,需要三台物理/虚拟机最少.
| 主机 | IP | 功能 | 备注 | 补充 |
|---|---|---|---|---|
| master | xx.xx.xx.88 | etcd,apiserver,controller-manager,scheduler | ||
| node1 | xx.xx.xx.91 | docker-engine,kubelet,proxy | flannel | |
| node2 | xx.xx.xx.92 | flannel | ||
| node3^*^ | xx.xx.xx.93 | harbor | 镜像仓库 | jenkins本地构建 |
| node4^*^ | xx.xx.xx.94 | gogs+jenkins | 代码仓库 | 也可能是gitlab |
A.基础环境准备
因为k8s跟docker有很多地方会跟linux kernel有相关冲突,包括SELinux,iptables,等等.所以最好提前布置好环境.
关闭swap
swapoff -a,再把/etc/fstab 文件中带有swap 的行删了Kubernetes 1.8开始要求关闭系统的Swap,如果不关闭,默认配置下kubelet将无法启动。可以通过kubelet的启动参数
--fail-swap-on=false更改这个限制。 所以简单起见选择关闭没有可以略过. 如图cent7.4需要删除最后一行.为了确认关闭成功.输入
free -m查看(正常如图)安装以下两个工具.
1
2$yum install -y ebtables socat #cent下安装,ubuntu自行更改命令
$sysctl net.bridge.bridge-nf-call-iptables=1 #IPv4 iptables 链设置 CNI插件需要
发现报错.提示文件不存在….醉了,先跳过看看.
关闭SELinux,它跟k8s冲突.
1
setenforce 0 #有些会提示SELinux is Disabled,我这没提示..
关闭系统防火墙 & 修改主机名
Reason:如果各个主机启用了防火墙,需要开放Kubernetes各个组件所需要的端口,可以查看Installing kubeadm中的”Check required ports”一节。 这里简单起见在各节点禁用防火墙(会有什么隐患呢?
1
2
3
4
5
6
7
8
9systemctl disable firewalld.service
输出如下
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
systemctl stop firewalld.service #无提示
修改主机名. 方便区分
hostnamectl set-hostname k8-master
hostnamectl set-hostname k8-node1
hostnamectl set-hostname k8-node2 #3,4node 待定. 因为harbor跟gogs并不是最小环境需要的.安装Docker
这里也有一些关键的东西要注意,如果用于生产环境, 那么应该选择当前k8版本最适合的docker版本,而不是过早或者过新的docker版本,以免有不可测的问题. k8s_1.8已经针对Docker的1.11.2, 1.12.6, 1.13.1和17.03.2等版本做了验证。 这里选的是1.12.6版
其次安装方法也有多种,这里就推荐用yum了.然后具体参数有如下选择.安装完也要检查确认一下版本,以及后续事项.
1
2
3
4
5
6
7
8
9
10
11yum install -y docker #这是最常规的做法. 装完是1.12.6
第二种,不确定这样是不是下的更新?
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
安装完成后检查版本
yum list docker-ce.x86_64 --showduplicates |sort -r
docker -v # 显示Docker version 1.12.6, build 85d7426/1.12.6Docker从1.13版本开始调整了默认的防火墙规则,禁用了iptables filter表中FOWARD链,这样会引起Kubernetes集群中跨Node的Pod无法通信,需要在各个Docker节点执行下面的命令
1
$ iptables -P FORWARD ACCEPT #1.12这里应该是不用的,严谨起见还是丢个给后面参考.
检查一下docker的info里面cgroups的驱动,要与k8的配置保持一致
1
docker info |grep Cg #输出 Cgroup Driver: systemd
B.创建CA证书和秘钥
k8的各个组件通信安全是一个很大的问题,1.6版之后还引入了RBAC的权限控制机制.(这个比较复杂,之后会单独研究). 所以使用了TLS证书对通信进行加密,这里使用PKI工具集的
cfssl;来生成CA证书和秘钥文件,CA是自签名的证书,用来签名后面创建的其他TLS证书.1.安装配置cfssl
一般是三步.
wget/curl下载,移动, 赋权. 这里可以把1,2合并一下, 赋权批量.1
2
3
4
5
6
7
8
9
10
11
12
13安装cfssl并给权限
curl -s -L -o /root/local/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
curl -s -L -o /root/local/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
curl -s -L -o /root/local/bin/cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x /bin/cfssl*
定义环境变量,创建ssl文件夹
export PATH=/root/local/bin:$PATH
mkdir ssl #位置随意,规律就行
cd ssl
生成默认的配置文件
cfssl print-defaults config > config.json
cfssl print-defaults csr > csr.json2.创建自己的CA
之前已经有config.json & csr.json的模板了,现在修改我们需要的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#第一个是ca-config.json
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"server auth"
],
"expiry": "8760h"
}
}
}
}
#第二个是ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "WuHan",
"O":"k8s",
"OU":"System",
"ST": "WuHan"
}
]
}这其中参数意义如下:
- ca-config.json :可以定义多个 profiles,分别指定不同的过期时间、使用
场景等参数.后续在签名证书时使用某个 profile. - signing :表示该证书可用于签名其它证书;生成的 ca.pem 证书中CA=TRUE.
- server auth :表示 client 可以用该 CA 对 server 提供的证书进行验证.
- client auth :表示 server 可以用该 CA 对 client 提供的证书进行验证.
- “CN”: Common Name ,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法.
- “O”: Organization ,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group).
3.生成CA证书和私钥 & 分发
cfssl会根据刚才的配置文件来进行生成. 注意检查别写错打错..
1
2
3
4
5
6
7
8
9
10[root@k8-master ssl]$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2017/12/01 08:42:48 [INFO] generating a new CA key and certificate from CSR
2017/12/01 08:42:48 [INFO] generate received request
2017/12/01 08:42:48 [INFO] received CSR
2017/12/01 08:42:48 [INFO] generating key: rsa-2048
2017/12/01 08:42:48 [INFO] encoded CSR
2017/12/01 08:42:48 [INFO] signed certificate with serial number 1525916857221429xxxxxxxxx1123
Request failed: #我去,现在看到failed就头疼..发现是 -bare 打成 =bare了.重新生成没报错了
[root@k8-master ssl]$ ls ca*
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem把生成好的CA证书 & 秘钥文件 & 配置文件拷贝到所有节点的 /etc/kubernetes/ssl 下.(当然要先生成)
1
2sudo mkdir -p /etc/kubernetes/ssl
sudo cp ca* /etc/kubernetes/ssl4.校验证书
使用 openssl 命令进行校验. 以校验kubernetes 证书为例这里
- client certificate: 用于服务端认证客户端,例如etcdctl、etcd proxy、fleetctl、docker客户端
- server certificate: 服务端使用,客户端以此验证服务端身份,例如docker服务端、kube-apiserver
- peer certificate: 双向证书,用于etcd集群成员间通信
C.安装etcd
etcd作为一个高可用键值存储系统,天生就是为集群化而设计的。由于Raft算法在做决策时需要多数节点的投票,所以etcd一般部署集群推荐奇数个节点,推荐的数量为3、5或者7个节点构成一个集群。 偶数可能会有天坑出现…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51wget https://github.com/coreos/etcd/releases/download/v3.2.10/etcd-v3.2.10-linux-
amd64.tar.gz #wget自行yum安一下,网上教程大多是3.1.x的etcd,3.2差别比较大. 注意迁移.
tar -xvzf etcd-v3.2.10-linux-amd64.tar.gz #然后新建/etc/etcd文件夹,cd过去
vim etcd.conf #把下面的配置复制进去.有需要的地方修改.
[member]
ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_WAL_DIR=""
ETCD_SNAPSHOT_COUNT="10000"
ETCD_HEARTBEAT_INTERVAL="100"
ETCD_ELECTION_TIMEOUT="1000"
ETCD_LISTEN_PEER_URLS="http://localhost:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_MAX_SNAPSHOTS="5"
ETCD_MAX_WALS="5"
ETCD_CORS=""
# [cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380"
if you use different ETCD_NAME (e.g. test), set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..."
ETCD_INITIAL_CLUSTER="default=http://localhost:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_DISCOVERY=""
ETCD_DISCOVERY_SRV=""
ETCD_DISCOVERY_FALLBACK="proxy"
ETCD_DISCOVERY_PROXY=""
# [proxy]
ETCD_PROXY="off"
ETCD_PROXY_FAILURE_WAIT="5000"
ETCD_PROXY_REFRESH_INTERVAL="30000"
ETCD_PROXY_DIAL_TIMEOUT="1000"
ETCD_PROXY_WRITE_TIMEOUT="5000"
ETCD_PROXY_READ_TIMEOUT="0"
# [security]
ETCD_CERT_FILE=""
ETCD_KEY_FILE=""
ETCD_CLIENT_CERT_AUTH="false"
ETCD_TRUSTED_CA_FILE=""
ETCD_PEER_CERT_FILE=""
ETCD_PEER_KEY_FILE=""
ETCD_PEER_CLIENT_CERT_AUTH="false"
ETCD_PEER_TRUSTED_CA_FILE=""
[logging]
ETCD_DEBUG="false"
examples for -log-package-levels etcdserver=WARNING,security=DEBUG
ETCD_LOG_PACKAGE_LEVELS=""然后将源文件中的etcd,etcdctl复制到 /usr/bin下,把下面的内容写到 /usr/lib/systemd/system/etcd.service文件中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
User=etcd
# set GOMAXPROCS to number of processors
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --name=\"${ETCD_NAME}\" --data-dir=\"${ETCD_DATA_DIR}\" --listen-client-urls=\"${ETCD_LISTEN_CLIENT_URLS}\""
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target最后启动etcd并检查(这里发现开始报错,查看日志)
1
2
3
4
5systemctl enable etcd
Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service.
systemctl start etcd
systemctl status etcd
etcdctl ls- ca-config.json :可以定义多个 profiles,分别指定不同的过期时间、使用
B.离线安装
参考离线源:
下载源码包(并校验)
地址从k8官方github仓库down下来.下载的时候需要开启代理,否则速度感人,7.4需要安装一下wget.完了后验证一下sha256.win下powershell自带有hash校验工具. (今天才知道,学习记录一下)
1
2
3
4$ Get-FileHash D:\kubernetes-server-linux-amd64.tar.gz -Algorithm sha256
Algorithm Hash Path
--------- ----------------- -------------
SHA256 89FEA17D256F68095371DCDF21A2E1AEB89B024..... D:\kubernetes...解压并查看目录
1
2
3
4
5
6
7
8
9
10cd kubernetes/server/bin #你可以pc下载然后sftp/scp发送到/root 下.其他路径自己找
以下是bin下列表
apiextensions-apiserver kube-aggregator.tar kubefed
cloud-controller-manager kube-apiserver kubelet
cloud-controller-manager.docker_tag kube-apiserver.docker_tag kube-proxy
cloud-controller-manager.tar kube-apiserver.tar kube-proxy.docker_tag
hyperkube kube-controller-manager kube-proxy.tar
kubeadm kube-controller-manager.docker_tag kube-scheduler
kube-aggregator kube-controller-manager.tar kube-scheduler.docker_tag
kube-aggregator.docker_tag kubectl kube-scheduler.tar核心的是kubeadm,kubectl,kube-scheduler,kube-apiserver等,看大小50多M以上的就是核心组件.常见8只
移动核心文件
1 | $ cp -r server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin/ |
完成后,可以看到是接近600M的.
- 创建kubectl & apiserver通信证书
0x02.问题
简单的问题排查命令
1.如何排查问题
- kubectl get rc 查看replicationcontroller 信息
- kubectl get pods 查看集群内的pos信息,可以查看pods的状态
- kubectl get events 非常有用,可以看到集群内发生的事,无论是正常发生的,还是有错误都可以看到
- kubectl logs pod-name 查看pod的系统日志,及运行在pod内的应用等日志





