1.规划
角色 | IP | 主机名 |
master/etcd | 10.0.0.115 | master |
node1/master/etcd | 10.0.0.116 | node1 |
node2/master/etcd | 10.0.0.117 | node2 |
node3 | 10.0.0.118 | node3 |
2.基础环境设置
2.1设置主机名
hostnamectl set-hostname XXXX
2.2做免密
在master上操作
[root@master .ssh]# ssh-keygen -t rsa
[root@master .ssh]# cat id_rsa.pub >authorized_keys
[root@master .ssh]# scp id_rsa* 10.0.0.206:/root/.ssh/
[root@master .ssh]# scp id_rsa* 10.0.0.208:/root/.ssh/
[root@node1 .ssh]# cat id_rsa.pub >authorized_keys ##两台node上都要操作
[root@node2 .ssh]# cat id_rsa.pub >authorized_keys
2.3安装ansible(也可以不安装,方便传文件)
这里只需在master1节点安装即可,后续一些操作均在此机器上执行,然后把生成的文件分发至对应节点
yum install -y epel-release
yum install ansible -y
[root@master ~]# ansible --version
定义主机组:
[root@master ~]# cat /etc/ansible/hosts
[k8s-master]
10.0.0.115
10.0.0.116
10.0.0.117
[k8s-all]
10.0.0.115
10.0.0.116
10.0.0.117
10.0.0.118
[k8s-node]
10.0.0.116
10.0.0.117
10.0.0.118
[root@master ~]# ansible all -m ping
2.4关闭防火墙/selinux
[root@master ~]# ansible all -m shell -a 'systemctl stop firewalld'
2.5设置内核
[root@master ~]# ansible all -m shell -a 'cat /proc/sys/net/bridge/bridge-nf-call-iptables'
若为1就正常,为0需要修改
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#vm.swappiness=0
sysctl -p
2.6时间同步
[root@master ~]# ansible all -m yum -a "name=ntpdate state=latest"
ansible k8s-all -m cron -a "name='k8s cluster crontab' minute=*/30 hour=* day=* month=* weekday=* job='ntpdate ntp1.aliyun.com >/dev/null 2>&1'"
2.7创建集群目录
[root@master ~]# ansible all -m file -a 'path=/etc/kubernetes/ssl state=directory'
[root@master ~]# ansible all -m file -a 'path=/etc/kubernetes/config state=directory'
## k8s-master01节点所需目录
[root@k8s-master01 ~]# mkdir /opt/k8s/{certs,cfg,unit} -p
/etc/kubernetes/ssl #集群使用证书目录
/etc/kubernetes/config #集群各组件加载配置文件存放路径
/opt/k8s/certs/ #集群证书制作目录
/opt/k8s/cfg/ #集群组件配置文件制作目录
/opt/k8s/unit/ #集群组件启动脚本制作目录
3.创建证书
使用证书的组件如下:
- etcd:使用 ca.pem、etcd-key.pem、etcd.pem;(etcd对外提供服务、节点间通信(etcd peer)使用同一套证书)
- kube-apiserver:使用 ca.pem、ca-key.pem、kube-apiserver-key.pem、kube-apiserver.pem;
- kubelet:使用 ca.pem ca-key.pem;
- kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem;
- kubectl:使用 ca.pem、admin-key.pem、admin.pem;
- kube-controller-manager:使用 ca-key.pem、ca.pem、kube-controller-manager.pem、kube-controller-manager-key.pem;
- kube-scheduler:使用ca-key.pem、ca.pem、kube-scheduler-key.pem、kube-scheduler.pem;
3.1安装cfssl
生成证书时可在任一节点完成,这里在master主机执行,证书只需要创建一次即可,以后在向集群中添加新节点时只要将 /etc/kubernetes/ssl 目录下的证书拷贝到新节点上即可。
1[root@k8s-master01 ~]# mkdir k8s/cfssl -p
2[root@k8s-master01 ~]# cd k8s/cfssl/
3[root@k8s-master01 cfssl]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
4[root@k8s-master01 cfssl]# chmod +x cfssl_linux-amd64
5[root@k8s-master01 cfssl]# cp cfssl_linux-amd64 /usr/local/bin/cfssl
6[root@k8s-master01 cfssl]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
7[root@k8s-master01 cfssl]# chmod +x cfssljson_linux-amd64
8[root@k8s-master01 cfssl]# cp cfssljson_linux-amd64 /usr/local/bin/cfssljson
9[root@k8s-master01 cfssl]# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
10[root@k8s-master01 cfssl]# chmod +x cfssl-certinfo_linux-amd64
11[root@k8s-master01 cfssl]# cp cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
3.2创建CA根证书
由于维护多套CA实在过于繁杂,这里CA证书用来签署集群其它组件的证书
这个文件中包含后面签署etcd、kubernetes等其它证书的时候用到的配置
vim /opt/k8s/certs/ca-config.json
1{
2 "signing": {
3 "default": {
4 "expiry": "87600h"
5 },
6 "profiles": {
7 "kubernetes": {
8 "usages": [
9 "signing",
10 "key encipherment",
11 "server auth",
12 "client auth"
13 ],
14 "expiry": "87600h"
15 }
16 }
17 }
18}
19
20说明:
21ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
22signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
23server auth:表示client可以用该 CA 对server提供的证书进行验证;
24client auth:表示server可以用该CA对client提供的证书进行验证;
25expiry: 表示证书过期时间,我们设置10年,当然你如果比较在意安全性,可以适当减少
3.3创建 CA 证书签名请求模板
vim /opt/k8s/certs/ca-csr.json
1{
2 "CN": "kubernetes",
3 "key": {
4 "algo": "rsa",
5 "size": 2048
6 },
7 "names": [
8 {
9 "C": "CN",
10 "ST": "ShangHai",
11 "L": "ShangHai",
12 "O": "k8s",
13 "OU": "System"
14 }
15 ]
16}
3.4生成CA证书、私钥和csr证书签名请求
该命令会生成运行CA所必需的文件ca-key.pem
(私钥)和ca.pem
(证书),还会生成ca.csr
(证书签名请求),用于交叉签名或重新签名。
[root@master cfssl]# cd /opt/k8s/certs/
安装cfssl证书命令: ##忽略此步,直接进行证书生成即可
[root@master certs]# curl -s -L -o /bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
[root@master certs]# curl -s -L -o /bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
[root@master certs]# curl -s -L -o /bin/cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
[root@master certs]# chmod +x /bin/cfssl*
证书生成:
[root@master certs]# cfssl gencert -initca /opt/k8s/certs/ca-csr.json | cfssljson -bare ca
1[root@master certs]# cfssl gencert -initca /opt/k8s/certs/ca-csr.json | cfssljson -bare ca
22019/06/26 17:24:59 [INFO] generating a new CA key and certificate from CSR
32019/06/26 17:24:59 [INFO] generate received request
42019/06/26 17:24:59 [INFO] received CSR
52019/06/26 17:24:59 [INFO] generating key: rsa-2048
62019/06/26 17:25:00 [INFO] encoded CSR
72019/06/26 17:25:00 [INFO] signed certificate with serial number 585032203412954806850533434549466645110614102863
3.5分发证书
所有节点都得分发
[root@master certs]# ansible all -m copy -a 'src=/opt/k8s/certs/ca.csr dest=/etc/kubernetes/ssl/'
[root@master certs]# ansible all -m copy -a 'src=/opt/k8s/certs/ca-key.pem dest=/etc/kubernetes/ssl/'
[root@master certs]# ansible all -m copy -a 'src=/opt/k8s/certs/ca.pem dest=/etc/kubernetes/ssl/'
4.部署ETCD
etcd 是k8s集群最重要的组件,用来存储k8s的所有服务信息, etcd 挂了,集群就挂了,这里把etcd部署在master节点上,etcd集群采用raft算法选举Leader, 由于Raft算法在做决策时需要多数节点的投票,所以etcd一般部署集群推荐奇数个节点,推荐的数量为3、5或者7个节点构成一个集群。
4.1下载etcd二进制文件
[root@master ~]# cd k8s/
[root@master k8s]# wget https://github.com/etcd-io/etcd/releases/download/v3.3.12/etcd-v3.3.12-linux-amd64.tar.gz
[root@master k8s]# tar -xf etcd-v3.3.12-linux-amd64.tar.gz
[root@master k8s]# cd etcd-v3.3.12-linux-amd64
##etcdctl是操作etcd的命令
[root@master etcd-v3.3.12-linux-amd64]# cp etcd /usr/local/bin/
[root@master etcd-v3.3.12-linux-amd64]# cd /usr/local/bin/
[root@master bin]# chmod 0755 etcd
[root@master bin]# ll -d etcd
-rwxr-xr-x 1 root root 19237536 6月 26 19:34 etcd
###三台master都需要拷贝
[root@k8s-master01 ~]# ansible k8s-master -m copy -a 'src=/root/k8s/etcd-v3.3.12-linux-amd64/etcd dest=/usr/local/bin/ mode=0755'
[root@k8s-master01 ~]# ansible k8s-master -m copy -a 'src=/root/k8s/etcd-v3.3.12-linux-amd64/etcdctl dest=/usr/local/bin/ mode=0755'
4.2创建etcd证书请求模板文件
vim /opt/k8s/certs/etcd-csr.json
1{
2 "CN": "etcd",
3 "hosts": [
4 "127.0.0.1",
5 "10.0.0.115",
6 "10.0.0.116",
7 "10.0.0.117"
8 ],
9 "key": {
10 "algo": "rsa",
11 "size": 2048
12 },
13 "names": [
14 {
15 "C": "CN",
16 "ST": "ShangHai",
17 "L": "ShangHai",
18 "O": "k8s",
19 "OU": "System"
20 }
21 ]
22}
说明:hosts中的IP为各etcd节点IP及本地127地址,在生产环境中hosts列表最好多预留几个IP,这样后续扩展节点或者因故障需要迁移时不需要再重新生成证书。
4.3生成证书及私钥
注意命令中使用的证书的具体位置
cd /opt/k8s/certs/
cfssl gencert -ca=/opt/k8s/certs/ca.pem \
-ca-key=/opt/k8s/certs/ca-key.pem \
-config=/opt/k8s/certs/ca-config.json \
-profile=kubernetes etcd-csr.json | cfssljson -bare etcd
1[root@master certs]# cfssl gencert -ca=/opt/k8s/certs/ca.pem \
2> -ca-key=/opt/k8s/certs/ca-key.pem \
3> -config=/opt/k8s/certs/ca-config.json \
4> -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
52019/06/26 19:40:18 [INFO] generate received request
62019/06/26 19:40:18 [INFO] received CSR
72019/06/26 19:40:18 [INFO] generating key: rsa-2048
82019/06/26 19:40:19 [INFO] encoded CSR
92019/06/26 19:40:19 [INFO] signed certificate with serial number 247828842085890133751587256942517588598704448904
102019/06/26 19:40:19 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
11websites. For more information see the Baseline Requirements for the Issuance and Management
12of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
13specifically, section 10.2.3 ("Information Requirements").
4.4查看证书
etcd.csr是签署时用到的中间文件,如果你不打算自己签署证书,而是让第三方的CA机构签署,只需要把etcd.csr文件提交给CA机构。
4.5证书分发
正常情况下只需要copy这三个文件即可,ca.pem(已经存在)、etcd-key.pem、etcd.pem
[root@master certs]# cp etcd-key.pem etcd.pem /etc/kubernetes/ssl/
4.6配置etcd配置文件
etcd.conf配置文件信息,配置文件中涉及证书,etcd用户需要对其有可读权限,否则会提示无法获取证书,644权限即可。
[root@master certs]# cd /opt/k8s/cfg/
[root@master cfg]# vim etcd.conf
1#[member]
2ETCD_NAME="etcd01"
3ETCD_DATA_DIR="/var/lib/etcd"
4#ETCD_SNAPSHOT_COUNTER="10000"
5#ETCD_HEARTBEAT_INTERVAL="100"
6#ETCD_ELECTION_TIMEOUT="1000"
7ETCD_LISTEN_PEER_URLS="http://10.0.0.115:2380"
8ETCD_LISTEN_CLIENT_URLS="http://10.0.0.115:2379,http://127.0.0.1:2379"
9#ETCD_MAX_SNAPSHOTS="5"
10#ETCD_MAX_WALS="5"
11#ETCD_CORS=""
12ETCD_AUTO_COMPACTION_RETENTION="1"
13ETCD_QUOTA_BACKEND_BYTES="8589934592"
14ETCD_MAX_REQUEST_BYTES="5242880"
15#[cluster]
16ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.115:2380"
17# if you use different ETCD_NAME (e.g. test),
18# set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..."
19ETCD_INITIAL_CLUSTER="etcd01=http://10.0.0.115:2380,etcd02=http://10.0.0.116:2380,etcd03=http://10.0.0.117:2380"
20ETCD_INITIAL_CLUSTER_STATE="new"
21ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"
22ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.115:2379"
23#[security]
24CLIENT_CERT_AUTH="true"
25ETCD_CA_FILE="/etc/kubernetes/ssl/ca.pem"
26ETCD_CERT_FILE="/etc/kubernetes/ssl/etcd.pem"
27ETCD_KEY_FILE="/etc/kubernetes/ssl/etcd-key.pem"
28PEER_CLIENT_CERT_AUTH="true"
29ETCD_PEER_CA_FILE="/etc/kubernetes/ssl/ca.pem"
30ETCD_PEER_CERT_FILE="/etc/kubernetes/ssl/etcd.pem"
31ETCD_PEER_KEY_FILE="/etc/kubernetes/ssl/etcd-key.pem"
参数解释:
- ETCD_NAME:etcd节点成员名称,在一个etcd集群中必须唯一性,可使用Hostname或者machine-id
- ETCD_LISTEN_PEER_URLS:和其它成员节点间通信地址,每个节点不同,必须使用IP,使用域名无效
- ETCD_LISTEN_CLIENT_URLS:对外提供服务的地址,通常为本机节点。使用域名无效
- ETCD_INITIAL_ADVERTISE_PEER_URLS:节点监听地址,并会通告集群其它节点
- ETCD_INITIAL_CLUSTER:集群中所有节点信息,格式为:节点名称+监听的本地端口,及:ETCD_NAME:https://ETCD_INITIAL_ADVERTISE_PEER_URLS
- ETCD_ADVERTISE_CLIENT_URLS:节点成员客户端url列表,对外公告此节点客户端监听地址,可以使用域名
- ETCD_AUTO_COMPACTION_RETENTION: 在一个小时内为mvcc键值存储的自动压实保留。0表示禁用自动压缩
- ETCD_QUOTA_BACKEND_BYTES: 事务中允许的最大操作数,默认1.5M,官方推荐10M,我这里设置5M,大家根据自己实际业务设置
- ETCD_MAX_REQUEST_BYTES: ETCDdb存储数据大小,默认2G,推荐8G
4.6分发etcd.conf配置文件到三台master
[root@k8s-master01 config]# ansible k8s-master -m copy -a 'src=/opt/k8s/cfg/etcd.conf dest=/etc/kubernetes/config/etcd.conf'
##登陆对应主机修改配置文件,把对应IP修改为本地IP
例如:
1[root@node1 ~]# cat /etc/kubernetes/config/etcd.conf
2#[member]
3ETCD_NAME="etcd02" ##名称唯一,不能重复
4ETCD_DATA_DIR="/var/lib/etcd"
5#ETCD_SNAPSHOT_COUNTER="10000"
6#ETCD_HEARTBEAT_INTERVAL="100"
7#ETCD_ELECTION_TIMEOUT="1000"
8ETCD_LISTEN_PEER_URLS="http://10.0.0.116:2380" ##修改成本机IP
9ETCD_LISTEN_CLIENT_URLS="http://10.0.0.116:2379,http://127.0.0.1:2379" ##修改成本机IP
10#ETCD_MAX_SNAPSHOTS="5"
11#ETCD_MAX_WALS="5"
12#ETCD_CORS=""
13ETCD_AUTO_COMPACTION_RETENTION="1"
14ETCD_QUOTA_BACKEND_BYTES="8589934592"
15ETCD_MAX_REQUEST_BYTES="5242880"
16#[cluster]
17ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.116:2380" ##修改成本机IP
18# if you use different ETCD_NAME (e.g. test),
19# set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..."
20ETCD_INITIAL_CLUSTER="etcd01=http://10.0.0.115:2380,etcd02=http://10.0.0.116:2380,etcd03=http://10.0.0.117:2380"
21ETCD_INITIAL_CLUSTER_STATE="new"
22ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"
23ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.116:2379" ##修改成本机IP
24#[security]
25CLIENT_CERT_AUTH="true"
26ETCD_CA_FILE="/etc/kubernetes/ssl/ca.pem"
27ETCD_CERT_FILE="/etc/kubernetes/ssl/etcd.pem"
28ETCD_KEY_FILE="/etc/kubernetes/ssl/etcd-key.pem"
29PEER_CLIENT_CERT_AUTH="true"
30ETCD_PEER_CA_FILE="/etc/kubernetes/ssl/ca.pem"
31ETCD_PEER_CERT_FILE="/etc/kubernetes/ssl/etcd.pem"
32ETCD_PEER_KEY_FILE="/etc/kubernetes/ssl/etcd-key.pem"
4.7配置etcd.service 启动文件及启动etcd
1[root@k8s-master01 ~]# vim /opt/k8s/unit/etcd.service
2
3[Unit]
4Description=Etcd Server
5After=network.target
6After=network-online.target
7Wants=network-online.target
8
9[Service]
10Type=notify
11WorkingDirectory=/var/lib/etcd/
12EnvironmentFile=-/etc/kubernetes/config/etcd.conf
13User=etcd
14# set GOMAXPROCS to number of processors
15ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/local/bin/etcd --name=\"${ETCD_NAME}\" --data-dir=\"${ETCD_DATA_DIR}\" --listen-client-urls=\"${ETCD_LISTEN_CLIENT_URLS}\""
16Restart=on-failure
17LimitNOFILE=65536
18
19[Install]
20WantedBy=multi-user.target
21[root@k8s-master01 ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/unit/etcd.service dest=/usr/lib/systemd/system/etcd.service'
22[root@k8s-master01 ~]# ansible k8s-master -m shell -a 'systemctl daemon-reload'
23[root@k8s-master01 ~]# ansible k8s-master -m shell -a 'systemctl enable etcd'
24[root@k8s-master01 ~]# ansible k8s-master -m shell -a 'systemctl start etcd'
[root@sunyun certs]# ansible k8s-master -m shell -a 'ps -efww|grep etcd'
4.8集群验证
[root@sunyun certs]# etcdctl cluster-health
[root@sunyun certs]# etcdctl member list
5.部署kebuctl
这里采用二进制安装,下载解压后,把对应组件二进制文件copy到指定节点
master节点组件:kube-apiserver、etcd、kube-controller-manager、kube-scheduler、kubectl
node节点组件:kubelet、kube-proxy、docker、coredns、calico
5.1部署master组件
5.1.1下载kubernetes二进制安装包
解压下载的压缩包,并把对应的二进制文件分发至对应master和node节点的指定位置
[root@sunyun ~]# cd k8s/
[root@sunyun k8s]# wget https://storage.googleapis.com/kubernetes-release/release/v1.14.1/kubernetes-server-linux-amd64.tar.gz
[root@sunyun k8s]# tar -xf kubernetes-server-linux-amd64.tar.gz
[root@sunyun k8s]# cd kubernetes
[root@sunyun kubernetes]# ll
总用量 34088
drwxr-xr-x. 2 root root 6 4月 9 01:51 addons
-rw-r--r--. 1 root root 28004039 4月 9 01:51 kubernetes-src.tar.gz
-rw-r--r--. 1 root root 6899720 4月 9 01:51 LICENSES
drwxr-xr-x. 3 root root 17 4月 9 01:46 server
##master二进制命令文件传输
[root@sunyun bin]# cd /root/k8s/kubernetes/server/bin
[root@sunyun bin]# scp ./{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kubeadm} 10.0.0.115:/usr/local/bin/
[root@sunyun bin]# scp ./{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kubeadm} 10.0.0.116:/usr/local/bin/
[root@sunyun bin]# scp ./{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kubeadm} 10.0.0.117:/usr/local/bin/
##node节点二进制文件传输
[root@sunyun bin]# scp ./{kube-proxy,kubelet} 10.0.0.116:/usr/local/bin/
[root@sunyun bin]# scp ./{kube-proxy,kubelet} 10.0.0.117:/usr/local/bin/
[root@sunyun bin]# scp ./{kube-proxy,kubelet} 10.0.0.118:/usr/local/bin/
5.1.2创建admin证书
kubectl用于日常直接管理K8S集群,kubectl要进行管理k8s,就需要和k8s的组件进行通信,也就需要用到证书。
kubectl部署在三台master节点
[root@sunyun ~]# vim /opt/k8s/certs/admin-csr.json
1{
2 "CN": "admin",
3 "hosts": [],
4 "key": {
5 "algo": "rsa",
6 "size": 2048
7 },
8 "names": [
9 {
10 "C": "CN",
11 "ST": "ShangHai",
12 "L": "ShangHai",
13 "O": "system:masters",
14 "OU": "System"
15 }
16 ]
17}
5.1.3生成admin证书和私钥
[root@sunyun ~]# cd /opt/k8s/certs/
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/opt/k8s/certs/ca-config.json \
-profile=kubernetes admin-csr.json | cfssljson -bare admin
5.1.4分发证书
[root@sunyun certs]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/admin-key.pem dest=/etc/kubernetes/ssl/'
[root@sunyun certs]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/admin.pem dest=/etc/kubernetes/ssl/'
5.1.5生成kubeconfig 配置文件
下面几个步骤会在家目录下的.kube生成config文件,之后kubectl和api通信就需要用到该文件,这也就是说如果在其他节点上操作集群需要用到这个kubectl,就需要将该文件拷贝到其他节点。
##设置集群参数
[root@k8s-master01 ~]# kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443
# 设置客户端认证参数
[root@k8s-master01 ~]# kubectl config set-credentials admin \
--client-certificate=/etc/kubernetes/ssl/admin.pem \
--embed-certs=true \
--client-key=/etc/kubernetes/ssl/admin-key.pem
#设置上下文参数
[root@k8s-master01 ~]# kubectl config set-context admin@kubernetes \
--cluster=kubernetes \
--user=admin
# 设置默认上下文
[root@k8s-master01 ~]# kubectl config use-context admin@kubernetes
以上操作会在当前目录下生成.kube/config文件,后续操作集群时,apiserver需要对该文件进行验证,创建的admin用户对kubernetes集群有所有权限(集群管理员)。
6.部署kube-apiserver
说明:
1、kube-apiserver是整个k8s集群中的数据总线和数据中心,提供了对集群的增删改查及watch等HTTP Rest接口
2、kube-apiserver是无状态的,虽然客户端如kubelet可通过启动参数"--api-servers"指定多个api-server,但只有第一个生效,并不能达到高可用的效果
6.1创建k8s集群各组件的运行用户
[root@sunyun ~]# ansible k8s-master -m group -a 'name=kube'
[root@sunyun ~]# ansible k8s-master -m user -a 'name=kube group=kube comment="Kubernetes user" shell=/sbin/nologin createhome=no'
6.2创建kube-apiserver证书请求文件
apiserver TLS 认证端口需要的证书
[root@sunyun ~]# vim /opt/k8s/certs/kube-apiserver-csr.json
1 {
2 "CN": "kubernetes",
3 "hosts": [
4 "127.0.0.1",
5 "10.0.0.115",
6 "10.0.0.116",
7 "10.0.0.117",
8 "10.254.0.1",
9 "localhost",
10 "kubernetes",
11 "kubernetes.default",
12 "kubernetes.default.svc",
13 "kubernetes.default.svc.cluster",
14 "kubernetes.default.svc.cluster.local"
15 ],
16 "key": {
17 "algo": "rsa",
18 "size": 2048
19 },
20 "names": [
21 {
22 "C": "CN",
23 "ST": "ShangHai",
24 "L": "ShangHai",
25 "O": "k8s",
26 "OU": "System"
27 }
28 ]
29}
hosts字段列表中,指定了master节点ip,本地ip,10.254.0.1为集群api-service ip,一般为设置的网络段中第一个ip
6.3生成 kubernetes 证书和私钥
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/opt/k8s/certs/ca-config.json \
-profile=kubernetes kube-apiserver-csr.json | cfssljson -bare kube-apiserver
2019/06/28 18:33:47 [INFO] generate received request
2019/06/28 18:33:47 [INFO] received CSR
2019/06/28 18:33:47 [INFO] generating key: rsa-2048
2019/06/28 18:33:47 [INFO] encoded CSR
2019/06/28 18:33:47 [INFO] signed certificate with serial number 283642706418045699183694890122146820794624697078
2019/06/28 18:33:47 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
6.4证书分发
[root@sunyun ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/kube-apiserver.pem dest=/etc/kubernetes/ssl'
[root@sunyun ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/kube-apiserver-key.pem dest=/etc/kubernetes/ssl'
6.5配置kube-apiserver客户端使用的token文件
kubelet 启动时向 kube-apiserver发送注册信息,在双向的TLS加密通信环境中需要认证,手工为kubelet生成证书/私钥在node节点较少且数量固定时可行,采用TLS Bootstrapping 机制,可使大量的node节点自动完成向kube-apiserver的注册请求。
原理:kubelet 首次启动时向 kube-apiserver 发送 TLS Bootstrapping 请求,kube-apiserver 验证 kubelet 请求中的 token 是否与它配置的 token.csv 一致,如果一致则自动为 kubelet生成证书和秘钥。
[root@sunyun ~]# head -c 16 /dev/urandom | od -An -t x | tr -d ' '
3394045ede72aad6cb39ebe9b1b92b90
[root@sunyun ~]# vim /opt/k8s/cfg/bootstrap-token.csv
3394045ede72aad6cb39ebe9b1b92b90,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
##分发token文件
[root@sunyun ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/cfg/bootstrap-token.csv dest=/etc/kubernetes/config/'
6.6生成 apiserver RBAC 审计配置文件
[root@sunyun ~]# vi /opt/k8s/cfg/audit-policy.yaml
1# Log all requests at the Metadata level.
2apiVersion: audit.k8s.io/v1
3kind: Policy
4rules:
5- level: Metadata
##分发审计文件
[root@sunyun ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/cfg/audit-policy.yaml dest=/etc/kubernetes/config/'
6.7编辑kube-apiserver核心文件
[root@k8s-master01 ~]# vim /opt/k8s/cfg/kube-apiserver.conf
1###
2# kubernetes system config
3#
4# The following values are used to configure the kube-apiserver
5#
6# The address on the local server to listen to.
7KUBE_API_ADDRESS="--advertise-address=10.0.0.115 --bind-address=0.0.0.0"
8# The port on the local server to listen on.
9KUBE_API_PORT="--secure-port=6443"
10# Port minions listen on
11# KUBELET_PORT="--kubelet-port=10250"
12# Comma separated list of nodes in the etcd cluster
13KUBE_ETCD_SERVERS="--etcd-servers=http://10.0.0.115:2379,http://10.0.0.116:2379,http://10.0.0.117:2379"
14# Address range to use for services
15KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
16# default admission control policies
17KUBE_ADMISSION_CONTROL="--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,Priority,ResourceQuota"
18# Add your own!
19KUBE_API_ARGS=" --allow-privileged=true \
20 --anonymous-auth=false \
21 --alsologtostderr \
22 --apiserver-count=3 \
23 --audit-log-maxage=30 \
24 --audit-log-maxbackup=3 \
25 --audit-log-maxsize=100 \
26 --audit-log-path=/var/log/kube-audit/audit.log \
27 --audit-policy-file=/etc/kubernetes/config/audit-policy.yaml \
28 --authorization-mode=Node,RBAC \
29 --client-ca-file=/etc/kubernetes/ssl/ca.pem \
30 --token-auth-file=/etc/kubernetes/config/bootstrap-token.csv \
31 --enable-bootstrap-token-auth \
32 --enable-garbage-collector \
33 --enable-logs-handler \
34 --endpoint-reconciler-type=lease \
35 --etcd-cafile=/etc/kubernetes/ssl/ca.pem \
36 --etcd-certfile=/etc/kubernetes/ssl/etcd.pem \
37 --etcd-keyfile=/etc/kubernetes/ssl/etcd-key.pem \
38 --etcd-compaction-interval=0s \
39 --event-ttl=168h0m0s \
40 --kubelet-http=true \
41 --kubelet-certificate-authority=/etc/kubernetes/ssl/ca.pem \
42 --kubelet-client-certificate=/etc/kubernetes/ssl/kube-apiserver.pem \
43 --kubelet-client-key=/etc/kubernetes/ssl/kube-apiserver-key.pem \
44 --kubelet-timeout=3s \
45 --runtime-config=api/all=true \
46 --service-node-port-range=30000-50000 \
47 --service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \
48 --tls-cert-file=/etc/kubernetes/ssl/kube-apiserver.pem \
49 --tls-private-key-file=/etc/kubernetes/ssl/kube-apiserver-key.pem \
50 --v=2"
个别参数解释:
- KUBE_API_ADDRESS:向集群成员通知apiserver消息的IP地址。这个地址必须能够被集群中其他成员访问。如果IP地址为空,将会使用--bind-address,如果未指定--bind-address,将会使用主机的默认接口地址
- KUBE_API_PORT:用于监听具有认证授权功能的HTTPS协议的端口。如果为0,则不会监听HTTPS协议。 (默认值6443)
- KUBE_ETCD_SERVERS:连接的etcd服务器列表
- KUBE_ADMISSION_CONTROL:控制资源进入集群的准入控制插件的顺序列表
- apiserver-count:集群中apiserver数量
- KUBE_SERVICE_ADDRESSES: CIDR IP范围,用于分配service 集群IP。不能与分配给节点pod的任何IP范围重叠
##分发参数配置文件,同时把参数中出现的IP修改为对应的本机IP
[root@k8s-master01 ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/cfg/kube-apiserver.conf dest=/etc/kubernetes/config/'
##创建日志目录并授权
[root@k8s-master01 ~]# ansible k8s-master -m file -a 'path=/var/log/kube-audit state=directory owner=kube group=kube'
6.8配置kube-apiserver启动脚本配置文件kube-apiserver.service
vim /opt/k8s/unit/kube-apiserver.service
1[Unit]
2Description=Kubernetes API Server
3Documentation=https://github.com/GoogleCloudPlatform/kubernetes
4After=network.target
5After=etcd.service
6
7[Service]
8EnvironmentFile=-/etc/kubernetes/config/kube-apiserver.conf
9User=kube
10ExecStart=/usr/local/bin/kube-apiserver \
11 $KUBE_LOGTOSTDERR \
12 $KUBE_LOG_LEVEL \
13 $KUBE_ETCD_SERVERS \
14 $KUBE_API_ADDRESS \
15 $KUBE_API_PORT \
16 $KUBELET_PORT \
17 $KUBE_ALLOW_PRIV \
18 $KUBE_SERVICE_ADDRESSES \
19 $KUBE_ADMISSION_CONTROL \
20 $KUBE_API_ARGS
21Restart=on-failure
22Type=notify
23LimitNOFILE=65536
24
25[Install]
26WantedBy=multi-user.target
## 分发apiserver启动脚本文件
[root@k8s-master01 ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/unit/kube-apiserver.service dest=/usr/lib/systemd/system/'
6.9启动kube-apiserver 服务
[root@k8s-master01 ~]# ansible k8s-master -m shell -a 'systemctl daemon-reload'
[root@k8s-master01 ~]# ansible k8s-master -m shell -a 'systemctl enable kube-apiserver'
[root@k8s-master01 ~]# ansible k8s-master -m shell -a 'systemctl start kube-apiserver'
[root@sunyun ~]# ansible k8s-master -m shell -a 'ps -efww|grep kube-apiserver'
[root@sunyun ~]# ansible k8s-master -m shell -a 'netstat -an|grep 6443'
7.部署controller-manage
1、Kubernetes控制器管理器是一个守护进程它通过apiserver监视集群的共享状态,并进行更改以尝试将当前状态移向所需状态。
2、多master节点中的kube-controller-manager服务是主备的关系,leader的选举,通过修改参数be-controller-manager,设置启动参数"--leader-elect=true"。
7.1创建kube-conftroller-manager证书签名请求
1、kube-controller-mamager连接 apiserver 需要使用的证书,同时本身 10257 端口也会使用此证书
2、kube-controller-mamager与kubei-apiserver通信采用双向TLS认证
[root@sunyun ~]# vim /opt/k8s/certs/kube-controller-manager-csr.json
1{
2 "CN": "system:kube-controller-manager",
3 "hosts": [
4 "127.0.0.1",
5 "10.0.0.115",
6 "10.0.0.116",
7 "10.0.0.117",
8 "localhost"
9 ],
10 "key": {
11 "algo": "rsa",
12 "size": 2048
13 },
14 "names": [
15 {
16 "C": "CN",
17 "ST": "ShangHai",
18 "L": "ShangHai",
19 "O": "system:kube-controller-manager",
20 "OU": "System"
21 }
22 ]
23}
说明:
1、hosts 列表包含所有 kube-controller-manager 节点 IP;
2、CN 为 system:kube-controller-manager;
O 为 system:kube-controller-manager;kube-apiserver预定义的 RBAC使用的ClusterRoleBindings system:kube-controller-manager将用户system:kube-controller-manager与ClusterRole system:kube-controller-manager绑定。
7.2生成kube-controller-manager证书与私钥
[root@sunyun ~]# cd /opt/k8s/certs/
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/opt/k8s/certs/ca-config.json \
-profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
2019/06/28 20:22:24 [INFO] generate received request
2019/06/28 20:22:24 [INFO] received CSR
2019/06/28 20:22:24 [INFO] generating key: rsa-2048
2019/06/28 20:22:24 [INFO] encoded CSR
2019/06/28 20:22:24 [INFO] signed certificate with serial number 463898038938255030318365806105397829277650185957
2019/06/28 20:22:24 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
7.3分发证书
[root@sunyun certs]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/kube-controller-manager-key.pem dest=/etc/kubernetes/ssl/'
[root@sunyun certs]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/kube-controller-manager.pem dest=/etc/kubernetes/ssl/'
7.4生成配置文件kube-controller-manager.kubeconfig
## 配置集群参数
### --kubeconfig:指定kubeconfig文件路径与文件名;如果不设置,默认生成在~/.kube/config文件。
### 后面需要用到此文件,所以把配置信息单独指向到指定文件中
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=kube-controller-manager.kubeconfig
## 配置客户端认证参数
### --server:指定api-server,若不指定,后面脚本中,可以指定master
### 认证用户为前文签名中的"system:kube-controller-manager";
kubectl config set-credentials system:kube-controller-manager \
--client-certificate=/etc/kubernetes/ssl/kube-controller-manager.pem \
--embed-certs=true \
--client-key=/etc/kubernetes/ssl/kube-controller-manager-key.pem \
--kubeconfig=kube-controller-manager.kubeconfig
## 配置上下文参数
kubectl config set-context system:kube-controller-manager@kubernetes \
--cluster=kubernetes \
--user=system:kube-controller-manager \
--kubeconfig=kube-controller-manager.kubeconfig
## 配置默认上下文
kubectl config use-context system:kube-controller-manager@kubernetes --kubeconfig=kube-controller-manager.kubeconfig
## 分发生成的配置文件
[root@sunyun certs]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/kube-controller-manager.kubeconfig dest=/etc/kubernetes/config/'
7.5编辑kube-controller-manager核心文件
controller manager 将不安全端口 10252 绑定到 127.0.0.1 确保 kubectl get cs 有正确返回;将安全端口 10257 绑定到 0.0.0.0 公开,提供服务调用;由于controller manager开始连接apiserver的6443认证端口,所以需要 --use-service-account-credentials 选项来让 controller manager 创建单独的 service account(默认 system:kube-controller-manager 用户没有那么高权限)
[root@sunyun certs]# vim /opt/k8s/cfg/kube-controller-manager.conf
1###
2# The following values are used to configure the kubernetes controller-manager
3
4# defaults from config and apiserver should be adequate
5
6# Add your own!
7KUBE_CONTROLLER_MANAGER_ARGS="--address=127.0.0.1 \
8 --authentication-kubeconfig=/etc/kubernetes/config/kube-controller-manager.kubeconfig \
9 --authorization-kubeconfig=/etc/kubernetes/config/kube-controller-manager.kubeconfig \
10 --bind-address=0.0.0.0 \
11 --cluster-name=kubernetes \
12 --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \
13 --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \
14 --client-ca-file=/etc/kubernetes/ssl/ca.pem \
15 --controllers=*,bootstrapsigner,tokencleaner \
16 --deployment-controller-sync-period=10s \
17 --experimental-cluster-signing-duration=87600h0m0s \
18 --enable-garbage-collector=true \
19 --kubeconfig=/etc/kubernetes/config/kube-controller-manager.kubeconfig \
20 --leader-elect=true \
21 --node-monitor-grace-period=20s \
22 --node-monitor-period=5s \
23 --port=10252 \
24 --pod-eviction-timeout=2m0s \
25 --requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem \
26 --terminated-pod-gc-threshold=50 \
27 --tls-cert-file=/etc/kubernetes/ssl/kube-controller-manager.pem \
28 --tls-private-key-file=/etc/kubernetes/ssl/kube-controller-manager-key.pem \
29 --root-ca-file=/etc/kubernetes/ssl/ca.pem \
30 --secure-port=10257 \
31 --service-cluster-ip-range=10.254.0.0/16 \
32 --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \
33 --use-service-account-credentials=true \
34 --v=2"
## 分发kube-controller-manager配置文件
ansible k8s-master -m copy -a 'src=/opt/k8s/cfg/kube-controller-manager.conf dest=/etc/kubernetes/config'
参数说明:
- address/bind-address:默认值:0.0.0.0,监听--secure-port端口的IP地址。关联的接口必须由集群的其他部分和CLI/web客户端访问。
- cluster-name:集群名称
- cluster-signing-cert-file/cluster-signing-key-file:用于集群范围认证
- controllers:启动的contrller列表,默认为”*”,启用所有的controller,但不包含” bootstrapsigner”与”tokencleaner”;
- kubeconfig:带有授权和master位置信息的kubeconfig文件路径
- leader-elect:在执行主逻辑之前,启动leader选举,并获得leader权
- service-cluster-ip-range:集群service的IP地址范围
7.6配置启动脚本
[root@sunyun ~]# vim /opt/k8s/unit/kube-controller-manager.service
1[Unit]
2Description=Kubernetes Controller Manager
3Documentation=https://github.com/GoogleCloudPlatform/kubernetes
4
5[Service]
6EnvironmentFile=-/etc/kubernetes/config/kube-controller-manager.conf
7User=kube
8ExecStart=/usr/local/bin/kube-controller-manager \
9 $KUBE_LOGTOSTDERR \
10 $KUBE_LOG_LEVEL \
11 $KUBE_MASTER \
12 $KUBE_CONTROLLER_MANAGER_ARGS
13Restart=on-failure
14LimitNOFILE=65536
15
16[Install]
17WantedBy=multi-user.target
## 分发启动脚本
ansible k8s-master -m copy -a 'src=/opt/k8s/unit/kube-controller-manager.service dest=/usr/lib/systemd/system/'
7.7启动kube-controller-manager服务
[root@sunyun ~]# ansible k8s-master -m shell -a 'systemctl daemon-reload'
[root@sunyun ~]# ansible k8s-master -m shell -a 'systemctl enable kube-controller-manager'
[root@sunyun ~]# ansible k8s-master -m shell -a 'systemctl start kube-controller-manager'
7.8查看leader主机
[root@sunyun ~]# kubectl get endpoints kube-controller-manager --namespace=kube-system -o yaml
8.kube-scheduler部署
1、Kube-scheduler作为组件运行在master节点,主要任务是把从kube-apiserver中获取的未被调度的pod通过一系列调度算法找到最适合的node,最终通过向kube-apiserver中写入Binding对象(其中指定了pod名字和调度后的node名字)来完成调度
2、kube-scheduler与kube-controller-manager一样,如果高可用,都是采用leader选举模式。启动后将通过竞争选举机制产生一个 leader 节点,其它节点为阻塞状态。当 leader 节点不可用后,剩余节点将再次进行选举产生新的 leader 节点,从而保证服务的可用性。
简单总结:
kube-scheduler负责分配调度Pod到集群内的某一个node节点上
监听kube-apiserver,查询还未分配的Node上的Pod
根据调度策略为这些Pod分配节点
8.1创建kube-scheduler证书签名请求
kube-scheduler 连接 apiserver 需要使用的证书,同时本身 10259 端口也会使用此证书
[root@sunyun ~]# vim /opt/k8s/certs/kube-scheduler-csr.json
1{
2 "CN": "system:kube-scheduler",
3 "hosts": [
4 "127.0.0.1",
5 "localhost",
6 "10.0.0.115",
7 "10.0.0.116",
8 "10.0.0.117"
9 ],
10 "key": {
11 "algo": "rsa",
12 "size": 2048
13 },
14 "names": [
15 {
16 "C": "CN",
17 "ST": "ShangHai",
18 "L": "ShangHai",
19 "O": "system:kube-scheduler",
20 "OU": "System"
21 }
22 ]
23}
8.2生成kube-scheduler证书与私钥
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/opt/k8s/certs/ca-config.json \
-profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
2019/06/28 21:29:48 [INFO] generate received request
2019/06/28 21:29:48 [INFO] received CSR
2019/06/28 21:29:48 [INFO] generating key: rsa-2048
2019/06/28 21:29:48 [INFO] encoded CSR
2019/06/28 21:29:48 [INFO] signed certificate with serial number 237230903244151644276886567039323221591882479671
2019/06/28 21:29:48 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
8.3分发证书
[root@sunyun certs]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/kube-scheduler-key.pem dest=/etc/kubernetes/ssl/'
[root@sunyun certs]# ansible k8s-master -m copy -a 'src=/opt/k8s/certs/kube-scheduler.pem dest=/etc/kubernetes/ssl/'
8.4生成配置文件kube-scheduler.kubeconfig
## 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=kube-scheduler.kubeconfig
## 配置客户端认证参数
kubectl config set-credentials "system:kube-scheduler" \
--client-certificate=/etc/kubernetes/ssl/kube-scheduler.pem \
--client-key=/etc/kubernetes/ssl/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
## 配置文件分发
[root@sunyun ~]# ansible k8s-master -m copy -a 'src=/root/kube-scheduler.kubeconfig dest=/etc/kubernetes/config/'
8.5编辑kube-scheduler核心文件
kube-shceduler 同 kube-controller manager 一样将不安全端口10259绑定在本地,安全端口10251对外公开
[root@sunyun ~]# vim /opt/k8s/cfg/kube-scheduler.conf
1###
2# kubernetes scheduler config
3
4# default config should be adequate
5
6# Add your own!
7KUBE_SCHEDULER_ARGS="--address=127.0.0.1 \
8 --authentication-kubeconfig=/etc/kubernetes/config/kube-scheduler.kubeconfig \
9 --authorization-kubeconfig=/etc/kubernetes/config/kube-scheduler.kubeconfig \
10 --bind-address=0.0.0.0 \
11 --client-ca-file=/etc/kubernetes/ssl/ca.pem \
12 --kubeconfig=/etc/kubernetes/config/kube-scheduler.kubeconfig \
13 --requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem \
14 --secure-port=10259 \
15 --leader-elect=true \
16 --port=10251 \
17 --tls-cert-file=/etc/kubernetes/ssl/kube-scheduler.pem \
18 --tls-private-key-file=/etc/kubernetes/ssl/kube-scheduler-key.pem \
19 --v=2"
## 分发配置文件
ansible k8s-master -m copy -a 'src=/opt/k8s/cfg/kube-scheduler.conf dest=/etc/kubernetes/config'
8.6编辑启动脚本
需要指定需要加载的配置文件路径
[root@sunyun ~]# vim /opt/k8s/unit/kube-scheduler.service
1[Unit]
2Description=Kubernetes Scheduler Plugin
3Documentation=https://github.com/GoogleCloudPlatform/kubernetes
4
5[Service]
6EnvironmentFile=-/etc/kubernetes/config/kube-scheduler.conf
7User=kube
8ExecStart=/usr/local/bin/kube-scheduler \
9 $KUBE_LOGTOSTDERR \
10 $KUBE_LOG_LEVEL \
11 $KUBE_MASTER \
12 $KUBE_SCHEDULER_ARGS
13Restart=on-failure
14LimitNOFILE=65536
15
16[Install]
17WantedBy=multi-user.target
##脚本分发
[root@sunyun ~]# ansible k8s-master -m copy -a 'src=/opt/k8s/unit/kube-scheduler.service dest=/usr/lib/systemd/system/'
8.7启动服务
[root@sunyun ~]# ansible k8s-master -m shell -a 'systemctl daemon-reload'
[root@sunyun ~]# ansible k8s-master -m shell -a 'systemctl enable kube-scheduler.service'
[root@sunyun ~]# ansible k8s-master -m shell -a 'systemctl start kube-scheduler.service'
8.8验证leader主机
[root@sunyun ~]# ansible k8s-master -m shell -a 'kubectl get endpoints kube-scheduler --namespace=kube-system -o yaml'
node2为leader
8.9验证master集群状态
在三个节点中,任一主机执行以下命令,都应返回集群状态信息
[root@sunyun ~]# ansible k8s-master -m shell -a 'kubectl get cs'
9.kube-apiserver部署
1、以下操作属于node节点上组件的部署,在master节点上只是进行文件配置,然后发布至各node节点。
2、若是需要master也作为node节点加入集群,也需要在master节点部署docker、kubelet、kube-proxy。
9.1安装docker-ce
kubelet启动,需要依赖docker服务,并且,k8s部署服务,都是基于docker进行运行
如果之前安装过 docker,请先删掉
yum remove docker docker-common docker-selinux docker-engine
## 安装依赖
[root@k8s-master01 ~]# ansible k8s-node -m shell -a 'yum install -y yum-utils device-mapper-persistent-data lvm2'
## 添加yum源
cd /etc/yum.repos.d/
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i 's#download.docker.com#mirrors.tuna.tsinghua.edu.cn/docker-ce#' /etc/yum.repos.d/docker-ce.repo
node节点都需要操作
## 安装指定版本docker
[root@k8s-master01 ~]# ansible k8s-node -m shell -a 'yum install docker-ce-18.09.5-3.el7 -y'
## 启动
[root@k8s-master01 ~]# ansible k8s-node -m shell -a 'systemctl enable docker'
[root@k8s-master01 ~]# ansible k8s-node -m shell -a 'systemctl start docker'
9.2创建nginx.conf配置文件
原理:为了保证 apiserver 的高可用,需要在每个 node 上部署 nginx 来反向代理(tcp)所有 apiserver;然后 kubelet、kube-proxy 组件连接本地 127.0.0.1:6443 访问 apiserver,以确保任何 master 挂掉以后 node 都不会受到影响;
## 创建nginx配置文件目录
[root@sunyun ~]# ansible k8s-node -m file -a 'path=/etc/nginx state=directory'
## 编辑nginx配置文件
[root@sunyun ~]# vim /opt/k8s/cfg/nginx.conf
1error_log stderr notice;
2
3worker_processes auto;
4events {
5 multi_accept on;
6 use epoll;
7 worker_connections 1024;
8}
9
10stream {
11 upstream kube_apiserver {
12 least_conn;
13 server 10.0.0.116:6443;
14 server 10.0.0.117:6443;
15 server 10.0.0.118:6443;
16 }
17
18 server {
19 listen 0.0.0.0:6443;
20 proxy_pass kube_apiserver;
21 proxy_timeout 10m;
22 proxy_connect_timeout 1s;
23 }
24}
## 分发nginx.conf至node节点
[root@sunyun ~]# ansible k8s-node -m copy -a 'src=/opt/k8s/cfg/nginx.conf dest=/etc/nginx/'
9.3配置Nginx基于docker进程,然后配置systemd来启动
vim /opt/k8s/unit/nginx-proxy.service
1[Unit]
2Description=kubernetes apiserver docker wrapper
3Wants=docker.socket
4After=docker.service
5
6[Service]
7User=root
8PermissionsStartOnly=true
9ExecStart=/usr/bin/docker run -p 127.0.0.1:6443:6443 \
10 -v /etc/nginx:/etc/nginx \
11 --name nginx-proxy \
12 --net=host \
13 --restart=on-failure:5 \
14 --memory=512M \
15 nginx:1.14.2-alpine
16ExecStartPre=-/usr/bin/docker rm -f nginx-proxy
17ExecStop=/usr/bin/docker stop nginx-proxy
18Restart=always
19RestartSec=15s
20TimeoutStartSec=30s
21
22[Install]
23WantedBy=multi-user.target
## 分发至node节点
[root@sunyun ~]# ansible k8s-node -m copy -a 'src=/opt/k8s/unit/nginx-proxy.service dest=/usr/lib/systemd/system/'
## 启动服务
ansible k8s-node -m shell -a 'systemctl daemon-reload'
ansible k8s-node -m shell -a 'systemctl enable nginx-proxy'
ansible k8s-node -m shell -a 'systemctl start nginx-proxy'
10.kubelet部署
Kubelet组件运行在Node节点上,维持运行中的Pods以及提供kuberntes运行时环境,主要完成以下使命:
1.监视分配给该Node节点的pods
2.挂载pod所需要的volumes
3.下载pod的secret
4.通过docker/rkt来运行pod中的容器
5.周期的执行pod中为容器定义的liveness探针
6.上报pod的状态给系统的其他组件
7.上报Node的状态
只在node节点上安装
10.1创建角色绑定
kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予 system:node-bootstrapper cluster 角色(role), 然后 kubelet 才能有权限创建认证请求(certificate signing requests):
[root@sunyun ~]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
--user=kubelet-bootstrap 是部署kube-apiserver时创建bootstrap-token.csv文件中指定的用户,同时也需要写入bootstrap.kubeconfig 文件
10.2创建kubelet kubeconfig文件,设置集群参数
## 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=bootstrap.kubeconfig
## 设置客户端认证参数
### tocker是前文提到的bootstrap-token.csv文件中token值
[root@sunyun ~]# cat /etc/kubernetes/config/bootstrap-token.csv
3394045ede72aad6cb39ebe9b1b92b90,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
kubectl config set-credentials kubelet-bootstrap \
--token=3394045ede72aad6cb39ebe9b1b92b90 \
--kubeconfig=bootstrap.kubeconfig
## 设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=bootstrap.kubeconfig
## 设置默认上下问参数
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
## 分发生成的集群配置文件到各node节点
ansible k8s-node -m copy -a 'src=/root/bootstrap.kubeconfig dest=/etc/kubernetes/config/'
10.3创建系统核心配置文件服务
用ansible分发至三个node节点,然后修改对应主机名及IP即可
vim /opt/k8s/cfg/kubelet.conf
###
# kubernetes kubelet (minion) config
# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--node-ip=10.0.0.116"
# The port for the info server to serve on
# KUBELET_PORT="--port=10250"
# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=node1"
# location of the api-server
# KUBELET_API_SERVER=""
# Add your own!
KUBELET_ARGS=" --address=0.0.0.0 \
--allow-privileged \
--anonymous-auth=false \
--authentication-token-webhook=true \
--authorization-mode=Webhook \
--bootstrap-kubeconfig=/etc/kubernetes/config/bootstrap.kubeconfig \
--client-ca-file=/etc/kubernetes/ssl/ca.pem \
--network-plugin=cni \
--cgroup-driver=cgroupfs \
--cert-dir=/etc/kubernetes/ssl \
--cluster-dns=10.254.0.2 \
--cluster-domain=cluster.local \
--cni-conf-dir=/etc/cni/net.d \
--eviction-max-pod-grace-period=30 \
--image-gc-high-threshold=80 \
--image-gc-low-threshold=70 \
--image-pull-progress-deadline=30s \
--kubeconfig=/etc/kubernetes/config/kubelet.kubeconfig \
--max-pods=100 \
--minimum-image-ttl-duration=720h0m0s \
--node-labels=node.kubernetes.io/k8s-node=true \
--pod-infra-container-image=gcr.azk8s.cn/google_containers/pause-amd64:3.1 \
--rotate-certificates \
--rotate-server-certificates \
--fail-swap-on=false \
--v=2"
说明:
- authorization-mode:kubelet认证模式
- network-plugin:网络插件名称
- cert-dir:TLS证书所在的目录
- eviction-max-pod-grace-period:终止pod最大宽限时间
- pod-infra-container-image:每个pod的network/ipc namespace容器使用的镜像
- rotate-certificates:当证书到期时,通过从kube-apiserver请求新的证书,自动旋转kubelet客户机证书
- hostname-override:设置node在集群中的主机名,默认使用主机hostname;如果设置了此项参数,kube-proxy服务也需要设置此项参数
10.4创建kubelet系统脚本
[root@sunyun ~]# vim /opt/k8s/unit/kubelet.service
[Unit]
Description=Kubernetes Kubelet Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=-/etc/kubernetes/config/kubelet.conf
ExecStart=/usr/local/bin/kubelet $KUBELET_ARGS
Restart=on-failure
KillMode=process
[Install]
WantedBy=multi-user.target
## 分发脚本配置文件
ansible k8s-node -m copy -a 'src=/opt/k8s/unit/kubelet.service dest=/usr/lib/systemd/system/'
## 创建kubelet数据目录
ansible k8s-node -m file -a 'path=/var/lib/kubelet state=directory'
10.5启动服务
[root@sunyun ~]# ansible k8s-node -m shell -a 'systemctl daemon-reload'
[root@sunyun ~]# ansible k8s-node -m shell -a 'systemctl enable kubelet'
[root@sunyun ~]# ansible k8s-node -m shell -a 'systemctl start kubelet'
10.6查看csr请求
查看未授权的csr请求,处于”Pending”状态
[root@sunyun ~]# kubectl get csr
10.7批准kubelet 的 TLS 证书请求
kubelet 首次启动向 kube-apiserver 发送证书签名请求,必须由 kubernetes 系统允许通过后,才会将该 node 加入到集群。
[root@sunyun ~]# kubectl certificate approve csr-fqln7
certificatesigningrequest.certificates.k8s.io/csr-fqln7 approved
[root@sunyun ~]# kubectl certificate approve csr-lj98c
certificatesigningrequest.certificates.k8s.io/csr-lj98c approved
## 查看node节点就绪状态
## 由于还没有安装网络,所以node节点还处于NotReady状态
[root@sunyun ~]# kubectl get nodes
11.kube-proxy部署
kube-proxy的作用主要是负责service的实现,具体来说,就是实现了内部从pod到service和外部的从node port向service的访问
## 开启ipvs
ansible k8s-node -m shell -a "yum install -y ipvsadm ipset conntrack"
ansible k8s-node -m shell -a 'modprobe -- ip_vs'
ansible k8s-node -m shell -a 'modprobe -- ip_vs_rr'
ansible k8s-node -m shell -a 'modprobe -- ip_vs_wrr'
ansible k8s-node -m shell -a 'modprobe -- ip_vs_sh'
ansible k8s-node -m shell -a 'modprobe -- nf_conntrack_ipv4'
11.1创建kube-proxy证书请求
[root@sunyun ~]# vim /opt/k8s/certs/kube-proxy-csr.json
1{
2 "CN": "system:kube-proxy",
3 "hosts": [],
4 "key": {
5 "algo": "rsa",
6 "size": 2048
7 },
8 "names": [
9 {
10 "C": "CN",
11 "ST": "ShangHai",
12 "L": "ShangHai",
13 "O": "system:kube-proxy",
14 "OU": "System"
15 }
16 ]
17}
11.2生成kube-proxy证书与私钥
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/opt/k8s/certs/ca-config.json \
-profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
11.3证书分发
ansible k8s-node -m copy -a 'src=/opt/k8s/certs/kube-proxy-key.pem dest=/etc/kubernetes/ssl/'
11.4创建kube-proxy kubeconfig文件
kube-proxy组件连接 apiserver 所需配置文件
## 配置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=kube-proxy.kubeconfig
## 配置客户端认证参数
kubectl config set-credentials system:kube-proxy \
--client-certificate=/opt/k8s/certs/kube-proxy.pem \
--embed-certs=true \
--client-key=/opt/k8s/certs/kube-proxy-key.pem \
--kubeconfig=kube-proxy.kubeconfig
## 配置集群上下文
kubectl config set-context system:kube-proxy@kubernetes \
--cluster=kubernetes \
--user=system:kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
## 配置集群默认上下文
##配置文件分发至node节点
ansible k8s-node -m copy -a 'src=/root/kube-proxy.kubeconfig dest=/etc/kubernetes/config/'
11.5配置kube-proxy参数
[root@sunyun ~]# vim /opt/k8s/cfg/kube-proxy.conf
1###
2# kubernetes proxy config
3# default config should be adequate
4# Add your own!
5KUBE_PROXY_ARGS=" --bind-address=0.0.0.0 \
6 --cleanup-ipvs=true \
7 --cluster-cidr=10.254.0.0/16 \
8 --hostname-override=node1 \ ###注意修改成每台node节点的hostname
9 --healthz-bind-address=0.0.0.0 \
10 --healthz-port=10256 \
11 --masquerade-all=true \
12 --proxy-mode=ipvs \
13 --ipvs-min-sync-period=5s \
14 --ipvs-sync-period=5s \
15 --ipvs-scheduler=wrr \
16 --kubeconfig=/etc/kubernetes/config/kube-proxy.kubeconfig \
17 --logtostderr=true \
18 --v=2"
ansible k8s-node -m copy -a 'src=/opt/k8s/cfg/kube-proxy.conf dest=/etc/kubernetes/config/'
### 修改hostname-override字段所属主机名
11.6kube-proxy系统服务脚本
[root@sunyun ~]# vim /opt/k8s/unit/kube-proxy.service
1[Unit]
2Description=Kubernetes Kube-Proxy Server
3Documentation=https://github.com/GoogleCloudPlatform/kubernetes
4After=network.target
5
6[Service]
7EnvironmentFile=-/etc/kubernetes/config/kube-proxy.conf
8ExecStart=/usr/local/bin/kube-proxy $KUBE_PROXY_ARGS
9
10Restart=on-failure
11LimitNOFILE=65536
12
13[Install]
14WantedBy=multi-user.target
## 分发至node节点
ansible k8s-node -m copy -a 'src=/opt/k8s/unit/kube-proxy.service dest=/usr/lib/systemd/system/'
11.7启动服务
[root@sunyun ~]# ansible k8s-node -m shell -a 'systemctl daemon-reload'
[root@sunyun ~]# ansible k8s-node -m shell -a 'systemctl enable kube-proxy'
[root@sunyun ~]# ansible k8s-node -m shell -a 'systemctl start kube-proxy'
11.8查看ipvs路由规则
检查LVS状态,可以看到已经创建了一个LVS集群,将来自10.254.0.1:443的请求转到三台master的6443端口,而6443就是api-server的端口
[root@sunyun ~]# ansible k8s-node -m shell -a 'ipvsadm -L -n'
12.网络Calico部署
由于K8S本身不支持网络,当 node 全部启动后,由于网络组件(CNI)未安装会显示为 NotReady 状态,需要借助第三方网络才能进行创建Pod,下面将部署 Calico 网络为K8S提供网络支持,完成跨节点网络通讯。
12.1下载Calico yaml
[root@k8s-master01 ~]# mkdir /opt/k8s/calico
[root@k8s-master01 ~]# cd /opt/k8s/calico/
[root@k8s-master01 calico]# wget http://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/calico.yaml
12.2修改配置文件
默认calico配置清单文件与部署的集群并不兼容,所以需要修改以下字段信息
## etcd 证书 base64 地址 (执行里面的命令生成的证书 base64 码,填入里面,编码并用双引号引起来即可)
vim calico.yaml
1apiVersion: v1
2
3kind: Secret
4
5type: Opaque
6
7metadata:
8
9 name: calico-etcd-secrets
10
11 namespace: kube-system
12
13data:
14
15 etcd-key: (cat /etc/kubernetes/ssl/etcd-key.pem | base64 | tr -d '\n')
16
17 etcd-cert: (cat /etc/kubernetes/ssl/etcd.pem | base64 | tr -d '\n')
18
19 etcd-ca: (cat /etc/kubernetes/ssl/ca.pem | base64 | tr -d '\n')
注意yaml文件对缩进有严格要求,最好用vi命令进行编辑
## ConfigMap
### 修改etcd地址
etcd_endpoints: "http://10.0.0.117:2379,http://10.0.0.116:2379,http://10.0.0.115:2379"
### 修改etcd证书位置
etcd_ca: "/calico-secrets/etcd-ca"
etcd_cert: "/calico-secrets/etcd-cert"
etcd_key: "/calico-secrets/etcd-key"
## 修改pod 分配的IP段(不能与node、service等地址同一网段)
- name: CALICO_IPV4POOL_CIDR
value: "10.254.64.0/18"
12.3加载应用
kubectl apply -f calico.yaml
12.4验证
[root@sunyun calico]# kubectl get pods -n kube-system -o wide
[root@sunyun calico]# kubectl get nodes
13.coredns部署
集群其他组件全部完成后我们应当部署集群 DNS 使 service 等能够正常解析
13.1下载yaml配置清单
[root@k8s-master01 ~]# mkdir /opt/k8s/coredns
[root@k8s-master01 ~]# cd /opt/k8s/coredns/
[root@k8s-master01 coredns]# wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed
[root@k8s-master01 coredns]# mv coredns.yaml.sed coredns.yaml
13.2修改默认配置清单文件
[root@k8s-master01 ~]# vim /opt/k8s/coredns/coredns.yaml
# 第一处修改
1apiVersion: v1
2
3kind: ConfigMap
4
5metadata:
6
7 name: coredns
8
9 namespace: kube-system
10
11data:
12
13 Corefile: |
14
15 .:53 {
16
17 errors
18
19 health
20
21 ready
22
23 kubernetes cluster.local 10.254.0.0/18 {
24
25 pods insecure
26
27 fallthrough in-addr.arpa ip6.arpa
28
29 }
30
31 prometheus :9153
32
33 forward . /etc/resolv.conf
34
35 cache 30
36
37 loop
38
39 reload
40
41 loadbalance
42
43 }
## 第二处修改
.....
搜索 /clusterIP 即可
clusterIP: 10.254.0.2
参数说明:
2)health:健康检查,提供了指定端口(默认为8080)上的HTTP端点,如果实例是健康的,则返回“OK”。
3)cluster.local:CoreDNS为kubernetes提供的域,10.254.0.0/18这告诉Kubernetes中间件它负责为反向区域提供PTR请求0.0.254.10.in-addr.arpa ..换句话说,这是允许反向DNS解析服务(我们经常使用到得DNS服务器里面有两个区域,即“正向查找区域”和“反向查找区域”,正向查找区域就是我们通常所说的域名解析,反向查找区域即是这里所说的IP反向解析,它的作用就是通过查询IP地址的PTR记录来得到该IP地址指向的域名,当然,要成功得到域名就必需要有该IP地址的PTR记录。PTR记录是邮件交换记录的一种,邮件交换记录中有A记录和PTR记录,A记录解析名字到地址,而PTR记录解析地址到名字。地址是指一个客户端的IP地址,名字是指一个客户的完全合格域名。通过对PTR记录的查询,达到反查的目的。)
4)proxy:这可以配置多个upstream 域名服务器,也可以用于延迟查找 /etc/resolv.conf 中定义的域名服务器
5)cache:这允许缓存两个响应结果,一个是肯定结果(即,查询返回一个结果)和否定结果(查询返回“没有这样的域”),具有单独的高速缓存大小和TTLs。
# 这里 kubernetes cluster.local 为 创建 svc 的 IP 段
kubernetes cluster.local 10.254.0.0/18
# clusterIP 为 指定 DNS 的 IP
13.3加载配置文件
[root@sunyun coredns]# kubectl apply -f coredns.yaml
## 查看资源创建
[root@sunyun ~]# kubectl get pod,svc -n kube-system -o wide
13.4测试dns解析
## 创建pod
[root@sunyun ~]# kubectl run nginx --image=nginx:1.14.2-alpine
可以看到pod被调度到node2节点上,IP地址10.254.75.2
## 创建service
[root@sunyun ~]# kubectl expose deployment nginx --port=80 --target-port=80
[root@sunyun ~]# kubectl get service
可以看到service nginx已经创建,并已经分配地址
## 验证dns解析
[root@sunyun ~]# kubectl run alpine --image=alpine -- sleep 3600
## 创建包含nslookup的pod镜像alpine
[root@k8s-master01 ~]# kubectl run alpine --image=alpine -- sleep 3600
## 查看pod名称
## 测试
[root@sunyun coredns]# kubectl exec -it alpine -- nslookup nginx
自个虚拟机环境出现异常,目前不知道什么原因
正确的测试结果如下图:
coredns参考文档: