K8S丨部署丨二进制部署Kubernetes
1. 环境说明
1.1 前置知识点
生产环境可部署Kubernetes集群的两种方式
目前生产部署Kubernetes集群主要有两种方式:
kubeadm
Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
二进制包
从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
之前发布的二进制部署因为没有写rabc授权和master节点过于空闲,于是重新写了这篇文章。
1.2 服务器规划
- k8s-master1&node1:
192.168.1.30
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- kubelet
- kube-proxy
- docker
- etcd
- k8s-master2&node2:
192.168.1.31
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- kubelet
- kube-proxy
- docker
- etcd
- k8s-node3:
192.168.1.32
- kubelet
- kube-proxy
- docker
- etcd
- k8s-node4:
192.168.1.33
- kubelet
- kube-proxy
- docker
- k8s-node5:
192.168.1.34
- kubelet
- kube-proxy
- docker
- Load Balancer-Master:
192.168.1.51
————|- Nginx L4—————————————-|— 192.168.1.50(VIP)
- Load Balancer-Backup:
192.168.1.52
————|- Nginx L4
- harbor:
192.168.1.60
- harbor
- 子网:
192.168.1.0/24
- 网关:
192.168.1.1
1.2.1 Kubernetes拓扑图
1.2.2 单Master架构图
1.3 系统环境初始化
1 | # centos7阿里源 |
PS:可以升级一下CentOS的Linux内核,CentOS自带的Linux为3.10,可以升级到长期支持版本5.4。(容器技术会依靠于Linux内核)
这篇文章是后写的,所以想到内核时已经部署好了,当然部署好了也可以升级内核,实测在node5升级了5.4内核,暂时没有出任何问题,后续继续查看。
2. 创建TLS证书及密钥
Kubernetes
系统的各组件需要使用 TLS
证书对通信进行加密,本文档使用 CloudFlare 的 PKI
工具集 cfssl
来生成 Certificate Authority (CA)
和其它证书;
本实例的证书创建都集中在本章节
2.1 证书说明
- 集群TLS认证需要的证书及密钥如下:
ca.pem
ca-key.pem
etcd.pem
etcd-key.pem
apiserver.pem
apiserver-key.pem
client.pem
(本实例用Bootstrapping,没用该证书)client-key.pem
(本实例用Bootstrapping,没用该证书)kubelet.pem
(本实例用Bootstrapping,没用该证书)kubelet-key.pem
(本实例用Bootstrapping,没用该证书)kube-proxy.pem
kube-proxy-key.pem
2.2 安装证书制作工具-CFSSL
1 | wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl |
- 关于CFSSL
cfssl
:证书签发的主要工具cfssl-json
:将cfssl生成的整数(json格式)变为文件承载式证书cfssl-certinfo
:验证证书的信息
2.3 创建CA证书
CA
配置文件
在harbor主机上制作证书,然后发放
mkdir -p cert && cd cert
过期时间设置成了 87600h(十年)
1 | cat > ca-config.json << EOF |
字段说明:
ca-config.json
:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;signing
:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;server auth
:表示client可以用该 CA 对server提供的证书进行验证;client auth
:表示server可以用该 CA 对client提供的证书进行验证;87600h
:十年
CA
证书申请表(生成CA自签名请求)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22cat > ca-csr.json << EOF
{
"CN": "k8s-ca",
"hosts": [ ],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "K8s",
"OU": "System"
}
],
"ca": {
"expiry": "87600h"
}
}
EOF
字段说明:
CN
:浏览器使用该字段验证网站是否合法,一般写的是域名,非常重要C
:国家ST
:州/省L
:地区/城市O
:组织名称/公司名称OU
:组织单位名称,公司部门
- 生成
1
2
3cfssl gencert -initca ca-csr.json | cfssl-json -bare ca
# 如果命令执行错误,则需要检查json文件
2.4 创建etcd证书
etcd
证书申请表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
26cat > etcd-csr.json << EOF
{
"CN": "k8s-etcd",
"hosts": [
"127.0.0.1",
"192.168.1.30",
"192.168.1.31",
"192.168.1.32",
"192.168.1.33",
"192.168.1.34"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
注:上述文件hosts字段中IP为所有etcd节点的集群内部通信IP,一个都不能少!为了方便后期扩容可以多写几个预留的IP。
- 生成
1
2
3cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer etcd-csr.json | cfssl-json -bare etcd
# 如果命令执行错误,则需要检查json文件
注:因为是对等证书,需要指定hosts(即只能在指定的IP上使用);hosts指定的IP均为etcd各节点的IP
参数说明:-ca=ca.pem
# CA证书-ca-key=ca-key.pem
# CA证书-config=ca-config.json
# CA配置文件-profile=peer
# 这个peer是指ca-config.json文件里的profilesetcd-csr.json
# etcd配置文件
2.5 创建apiserver证书
- 证书申请表
1 | cat > apiserver-csr.json << EOF |
- 字段说明:
hosts
:指定授权使用该证书的 IP 或域名列表,这里列出了 VIP 、apiserver节点 IP、kubernetes 服务 IP 和域名;- 域名最后字符不能是
kubernetes.default.svc.cluster.local.
(如为kubernetes.default.svc.cluster.local. ),否则解析时失败,提示:x509:cannot parse dnsName "kubernetes.default.svc.cluster.local."
;如果使用非cluster.local
域名,如jeremy.com
,则需要修改域名列表中的最后两个域名为:kubernetes.default.svc.jeremy
、kubernetes.default.svc.jeremy.com
- kubernetes 服务 IP 是 apiserver 自动创建的,一般是
--service-cluster-ip-range
参数指定的网段的第一个IP,如:192.168.80.1
,可以通过如下命令获取:kubectl get svc kubernetes
- 生成
1
2
3cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer apiserver-csr.json | cfssl-json -bare apiserver
# 如果命令执行错误,则需要检查json文件
2.6 创建kube-proxy证书
证书申请表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19cat > kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF生成
1
2
3cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer kube-proxy-csr.json | cfssl-json -bare kube-proxy
# 如果命令执行错误,则需要检查json文件
3. Etcd集群部署
hostname | 节点名称 | IP |
---|---|---|
k8s-master1 | etcd-1 | 192.168.1.30 |
k8s-master2 | etcd-2 | 192.168.1.31 |
k8s-node3 | etcd-3 | 192.168.1.32 |
3.1 安装
1 | wget https://github.com/etcd-io/etcd/releases/download/v3.4.13/etcd-v3.4.13-linux-amd64.tar.gz |
3.2 创建证书
请看2.4 创建
etcd
证书拷贝到证书
1
scp {ca,etcd,etcd-key}.pem k8s-master1:/opt/etcd/cert
3.3 各etcd节点配置文件
1 | cat > /opt/etcd/conf.d/etcd.conf << 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
:集群TokenETCD_INITIAL_CLUSTER_STATE
:加入集群的当前状态,new
是新集群,existing
表示加入已有集群
3.4 systemd管理etcd
systemd文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24cat > /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/conf.d/etcd.conf
ExecStart=/opt/etcd/bin/etcd \\
--cert-file=/opt/etcd/cert/etcd.pem \\
--key-file=/opt/etcd/cert/etcd-key.pem \\
--peer-cert-file=/opt/etcd/cert/etcd.pem \\
--peer-key-file=/opt/etcd/cert/etcd-key.pem \\
--trusted-ca-file=/opt/etcd/cert/ca.pem \\
--peer-trusted-ca-file=/opt/etcd/cert/ca.pem \\
--log-level=info \\
--logger=zap \\
--log-outputs=stderr
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF启动并设置开机启动
1
2
3
4systemctl daemon-reload
systemctl start etcd
systemctl status etcd
systemctl enable etcd
3.5 检查etcd集群节点健康情况
- etcd各节点健康情况
1
2
3
4
5
6/opt/etcd/bin/etcdctl \
--endpoints="https://192.168.1.30:2379,https://192.168.1.31:2379,https://192.168.1.32:2379" \
--cacert=/opt/etcd/cert/ca.pem \
--cert=/opt/etcd/cert/etcd.pem \
--key=/opt/etcd/cert/etcd-key.pem \
--write-out=table endpoint health
- etcd各节点状态情况
1
2
3
4
5
6/opt/etcd/bin/etcdctl \
--endpoints="https://192.168.1.30:2379,https://192.168.1.31:2379,https://192.168.1.32:2379" \
--cacert=/opt/etcd/cert/ca.pem \
--cert=/opt/etcd/cert/etcd.pem \
--key=/opt/etcd/cert/etcd-key.pem \
--write-out=table endpoint status
ps: 表格显示加
--write-out=table
4. Docker部署
一般情况只有node
节点才需要安装docker
的,但是本次实例master
节点同时也是node
节点,所以也需要安装docker
,所以本次实例给所有机器安装docker
4.1 下载解压二进制包
- 下载地址
- 安装
1
2
3
4
5
6
7
8
9
10
11
12tar -xzvf docker-19.03.9.tgz
mkdir -p /opt/docker/bin
mv docker/* /opt/docker/bin
ln -sv /opt/docker/bin/docker /usr/local/bin/
ln -sv /opt/docker/bin/containerd /usr/local/bin/
ln -sv /opt/docker/bin/containerd-shim /usr/local/bin/
ln -sv /opt/docker/bin/ctr /usr/local/bin/
ln -sv /opt/docker/bin/dockerd /usr/local/bin/
ln -sv /opt/docker/bin/docker-init /usr/local/bin/
ln -sv /opt/docker/bin/docker-proxy /usr/local/bin/
ln -sv /opt/docker/bin/runc /usr/local/bin/
4.2 配置文件
1 | mkdir -p /opt/docker/data /etc/docker |
bip:172.8.x.1/24,x按照宿主机IP地址最后一位来设置
insecure-registries:需要添加你harbor的域名,不然harbor无法登录
4.3 systemd管理docker
1 | cat > /usr/lib/systemd/system/docker.service << EOF |
4.4 启动docker
1 | systemctl daemon-reload && systemctl start docker |
5. Harbor部署
5.1 下载解压二进制包
- 下载地址
- 校验
下载对应版本的检验码进行校验:
v2.1.1校验码
然后使用 md5sum -c md5sum
来查看文件内容是否正确,如果正确,会显示下面的内容。
1 | [root@harbor opt]# md5sum -c md5sum |
如果你下载是
harbor-offline-installer-v2.1.1.tgz
,则这个才会显示ok;
而没下载的例如:harbor-online-installer-v2.1.1.tgz
,则会提示md5sum: harbor-online-installer-v2.1.1.tgz: No such file or directory
- 解压
1 | tar -xzvf harbor-offline-installer-v2.1.1.tgz |
5.2 配置文件
harbor.yml.tmpl
这个文件配置文件模板,可以按其格式来
去掉注释:grep -v "#" harbor.yml.tmpl
1 | cd /opt/harbor/ |
参数说明:
一般情况下,我们最少需要配置的内容如下:
hostname
需要配置为 127.0.0.1 之外的内容,以提供外部访问https
的配置需要同时配置证书,生产环境中,如果使用 SLB 或者使用其他应用统一提供 SSL 接入,则可以删除。harbor_admin_password
默认密码即可,但是初次使用登陆后台后需要修改密码。data_volume
根据自己实际情况修改宿主机的文件储存地址。
- 创建harbor数据存储目录
1
2mkdir -p /opt/harborData
mkdir -p /opt/harborData/logs
5.3 docker-compose启动harbor
下载安装docker-compose
1
2
3curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose启动harbor
修改完配置之后,使用 bash install.sh
进行应用安装。
1 | sh /opt/harbor/install.sh |
- 用
docker-compose
查看
5.4 nginx代理harbor本地端口
安装
1
yum install nginx -y
nginx配置文件
vim /etc/nginx/conf.d/harbor.conf
1
2
3
4
5
6
7
8server {
listen 80;
server_name harbor.jeremy.cn;
client_max_body_size 1000m;
location / {
proxy_pass http://127.0.0.1:8080;
}
}启动nginx
1
2
3systemctl start nginx
systemctl enable nginx
systemctl status nginx添加host记录
1 | cat >> /etc/hosts << EOF |
- 上传镜像
访问
http://harbor.jeremy.cn/
添加一个
public
库拉取
docker pull nginx
1 | [root@harbor harbor]# docker images |
打tag
1
docker tag c39a868aad02 harbor.jeremy.cn/public/nginx:latest
登录
1
2
3
4
5
6
7
8[root@harbor harbor]# docker login harbor.jeremy.cn
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
要登陆的需要在
/etc/docker/daemon.json
里面的insecure-registries
添加harbor的域名(harbor.jeremy.cn),不然无法使用http登录,https登录则需要配置中有https
如果之前的docker配置没有添加harbor的域名,则需要重新打包运行harbor,不然还是登录不了
- 推送镜像到harbor
1
2
3
4
5
6
7
8[root@harbor harbor]# docker push harbor.jeremy.cn/public/nginx:latest
The push refers to repository [harbor.jeremy.cn/public/nginx]
7b5417cae114: Pushed
aee208b6ccfb: Pushed
2f57e21e4365: Pushed
2baf69a23d7a: Pushed
d0fe97fa8b8c: Pushed
latest: digest: sha256:34f3f875e745861ff8a37552ed7eb4b673544d2c56c7cc58f9a9bec5b4b3530e size: 1362
6. Master节点部署
kube-apiserver
是Kubernetes最重要的核心组件之一,主要提供以下的功能:
- 提供集群管理的
REST API
接口,包括认证授权、数据校验以及集群状态变更等 - 提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd)。
hostname | 节点名称 | IP |
---|---|---|
k8s-master1 | master1 | 192.168.1.30 |
k8s-master2 | master2 | 192.168.1.31 |
- k8s-master1&node1:
192.168.1.30
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- kubelet
- kube-proxy
- docker
- etcd
- k8s-master2&node2:
192.168.1.31
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- kubelet
- kube-proxy
- docker
6.1 kube-apiserver部署
- 下载地址
- 从Github下载二进制文件
1
2
3下载地址: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.18.md#v1183
注:打开链接你会发现里面有很多包,下载一个server包就够了,包含了Master和Worker Node二进制文件。
1.18.10版本:wget https://storage.googleapis.com/kubernetes-release/release/v1.18.10/kubernetes-server-linux-amd64.tar.gz
- 解压和创建文件夹
分别在两台master上下载kubernetes-server-linux-amd64.tar.gz
1 | tar -xzvf kubernetes-server-linux-amd64.tar.gz -C /opt |
/opt/kubernetes/server/cert:存放证书
/opt/kubernetes/server/conf:存放启动配置文件
- 创建证书
- 查看 2.5 创建
apiserver
证书
- 拷贝证书
1
2
3
4scp /root/cert/{ca.pem,ca-key.pem,apiserver.pem,apiserver-key.pem,etcd.pem,etcd-key.pem} k8s-master1:/opt/kubernetes/server/cert
ls server/cert/
>> apiserver-key.pem apiserver.pem ca-key.pem ca.pem etcd-key.pem etcd.pem
注意私钥文件属性600
- 创建配置文件
1 | cat > /opt/kubernetes/server/conf.d/kube-apiserver.conf << EOF |
- systemd管理apiserver
1 | cat > /usr/lib/systemd/system/kube-apiserver.service << EOF |
- 添加环境变量
1
2
3
4
5
6
7cat >> /etc/profile << EOF
# kubernetes-master
export K8S_MASTER_HOME=/opt/kubernetes/server
export PATH=\$PATH:\$K8S_MASTER_HOME/bin
EOF
source /etc/profile
- 启动并设置开机启动
1
2
3
4systemctl daemon-reload
systemctl start kube-apiserver
systemctl enable kube-apiserver
systemctl status kube-apiserver
- 启用 TLS Bootstrapping 机制
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
工作流程:
# 1. 生成token
1 | head -c 16 /dev/urandom | od -An -t x | tr -d ' ' |
# 2. 创建上述配置文件中token文件
1 | cat > /opt/kubernetes/server/conf.d/token.csv << EOF |
# 3. 授权kubelet-bootstrap用户允许请求证书
1 | kubectl create clusterrolebinding kubelet-bootstrap \ |
6.2 kube-controller-manager部署
Controller Manager是Kubernetes最重要的核心组件之一,主要提供以下的功能:
- 主要kube-controller-manager和cloud-controller-manager组成,是Kubernetes的大脑,它通过apiserver监控整个集群的状态,并确保集群处于预期的工作状态。
- 创建配置文件
1 | cat > /opt/kubernetes/server/conf.d/kube-controller-manager.conf << EOF |
--master
:通过本地非安全本地端口8080
连接apiserver
。--leader-elect
:当该组件启动多个时,自动选举(HA)
- systemd管理controller-manager
1 | cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF |
- 启动并设置开机启动
1
2
3
4systemctl daemon-reload
systemctl start kube-controller-manager
systemctl enable kube-controller-manager
systemctl status kube-controller-manager
6.3 kube-scheduler部署
kube-scheduler
是Kubernetes
最重要的核心组件之一,主要提供以下的功能:
- 负责分配调度
Pod
到集群内的节点上,它监听kube-apiserver
,查询还未分配Node
的Pod
,然后根据调度策略为这些Pod
分配节点(更新Pod的NodeName
字段)。
- 创建配置文件
1 | cat > /opt/kubernetes/server/conf.d/kube-scheduler.conf << EOF |
- systemd管理scheduler
1 | cat > /usr/lib/systemd/system/kube-scheduler.service << EOF |
- 启动并设置开机启动
1
2
3
4systemctl daemon-reload
systemctl start kube-scheduler
systemctl enable kube-scheduler
systemctl status kube-scheduler
- 查看集群状态
所有组件都已经启动成功,通过kubectl工具查看当前集群组件状态:
1 | [root@k8s-master1 opt]# kubectl get cs |
- 同理把
master2
也部署好apiserver
,scheduler
,controller-manager
7. L4反向代理
- Load Balancer(Master):
192.168.1.51
- 192.168.1.50(VIP)- Nginx L4
- Load Balancer(Backup):
192.168.1.52
- Nginx L4
7.1 拓扑图
7.2 nginx部署
安装nginx
1
yum install nginx -y
nginx配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15vim /etc/nginx/nginx.conf # 黏贴到http标签外
stream {
# kubernetes api-server ip地址以及https端口
upstream kube-apiserver {
server 192.168.1.30:6443 max_fails=3 fail_timeout=30s;
server 192.168.1.31:6443 max_fails=3 fail_timeout=30s;
}
# 监听8443端口,将其接收的流量转发至指定proxy_pass
server {
listen 8443;
proxy_connect_timeout 2s;
proxy_timeout 900s;
proxy_pass kube-apiserver;
}
}启动nginx
1
systemctl start nginx && systemctl enable nginx && systemctl status nginx
7.3 keepalived部署
安装keepalived
1
yum install keepalived -y
监听脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19vim /etc/keepalived/check_port.sh
# keepalived 监控端口脚本
# 使用方法:
# 在keepalived的配置文件中
# vrrp_script check_port {# 创建一个vrrp_script脚本,检查配置
# script "/etc/keepalived/check_port.sh 8443" # 配置监听的端口
# interval 2 #检查脚本的频率,单位(秒)
# }
CHK_PORT=$1
if [ -n "$CHK_PORT" ];then
PORT_PROCESS=`ss -lnt|grep $CHK_PORT|wc -l`
if [ $PORT_PROCESS -eq 0 ];then
echo "Port $CHK_PORT Is Not Used,End."
exit 1
fi
else
echo "Check Port Cant Be Empty!"
fi添加可执行权限
1
chmod +x /etc/keepalived/check_port.sh
keepalived主配置文件
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70# 主服务器
cat > /etc/keepalived/keepalived.conf << EOF
# Configuration File for keepalived
global_defs {
# 机器标识符,一般设置为hostname
router_id load-balancer-master
}
vrrp_script chk_nginx {
# 调用脚本检测nginx监听的8443端口是否存在
script "/etc/keepalived/check_port.sh 8443"
interval 2
weight -20
}
vrrp_instance VI_1 {
state MASTER
interface ens192
# 虚拟路由组id,两边须一致
virtual_router_id 91
priority 100
advert_int 1
# 当前主机IP
mcast_src_ip 192.168.1.51
# 不抢占
nopreempt
# 高可用认证
authentication {
auth_type PASS
auth_pass jeremy # 认证密码,两边须一致
}
track_script {
chk_nginx
}
# 虚拟IP
virtual_ipaddress {
192.168.1.50
}
}
EOF
# 备服务器
cat > /etc/keepalived/keepalived.conf << EOF
# Configuration File for keepalived
global_defs {
router_id load-balancer-backup
}
vrrp_script chk_nginx {
script "/etc/keepalived/check_port.sh 8443"
interval 2
weight -20
}
vrrp_instance VI_1 {
state BACKUP
interface ens192
virtual_router_id 91
mcast_src_ip 192.168.1.52
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass jeremy
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.1.50
}
}
EOF启动keepalived
1
systemctl start keepalived && systemctl enable keepalived && systemctl status keepalived
8. Node节点部署
hostname | 节点名称 | IP |
---|---|---|
k8s-master1 | node1 | 192.168.1.30 |
k8s-master2 | node2 | 192.168.1.31 |
k8s-node3 | node3 | 192.168.1.32 |
k8s-node4 | node4 | 192.168.1.33 |
k8s-node5 | node5 | 192.168.1.34 |
node
节点主要部署两个服务kubelet
kube-proxy
docker
8.1 kubelet部署
- 下载地址
- 部署
kubernetes-node包里面的二进制文件跟kubernetes-server包里面给的是一样的
1 | tar -xzvf kubernetes-node-linux-amd64.tar.gz |
- 准备pause基础镜像
pause镜像是k8s里必不可少的以pod方式运行业务容器时的一个基础容器。
在harbor上拉取镜像:
docker pull kubernetes/pause
上传镜像到harbor仓库
1
2docker tag f9d5de079539 harbor.jeremy.cn/public/pause:latest
docker push harbor.jeremy.cn/public/pause:latest
登录harbor,创建目录,拷贝证书,环境变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 创建数据存储目录
mkdir /opt/kubernetes/node/kubeletData
# 登录harbor(账号:admin,密码:Harbor12345)
docker login harbor.jeremy.cn
# 拷贝证书
scp ca.pem k8s-master1:/opt/kubernetes/node/cert
# 环境变量
cat >> /etc/profile << EOF
# kubernetes-node
export K8S_NODE_HOME=/opt/kubernetes/node
export PATH=\$PATH:\$K8S_NODE_HOME/bin
EOF
source /etc/profile创建配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13cat > /opt/kubernetes/node/conf.d/kubelet.conf << EOF
KUBELET_OPTS="--hostname-override=k8s-master1 \\
--kubeconfig=/opt/kubernetes/node/conf.d/kubelet.kubeconfig \\
--bootstrap-kubeconfig=/opt/kubernetes/node/conf.d/kubelet-bootstrap.kubeconfig \\
--config=/opt/kubernetes/node/conf.d/kubelet-config.yml \\
--cert-dir=/opt/kubernetes/node/cert \\
--root-dir=/opt/kubernetes/node/kubeletData \\
--network-plugin=cni \\
--pod-infra-container-image=harbor.jeremy.cn/public/pause:latest \\
--log-dir=/opt/kubernetes/node/logs \\
--logtostderr=false \\
--v=2"
EOF参数说明:
--hostname-override
:显示名称,集群中唯一(需要修改)--kubeconfig
:空路径,会自动生成,后面用于连接apiserver--bootstrap-kubeconfig
:首次启动向apiserver申请证书--config
:配置参数文件--cert-dir
:kubelet证书生成目录--pod-infra-container-image
:管理Pod网络容器的镜像(这里用的是我们上传到harbor的pause镜像)--root-dir
:设置用于管理kubelet
文件的根目录(例如挂载卷的相关文件)(默认值为 “/var/lib/kubelet”)--network-plugin
:启用cni
,后面会部署fannel
网络组件
配置参数文件
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
32cat > /opt/kubernetes/node/conf.d/kubelet-config.yml << EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS:
- 192.168.80.2
clusterDomain: cluster.local
failSwapOn: false
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 2m0s
enabled: true
x509:
clientCAFile: /opt/kubernetes/node/cert/ca.pem
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
maxOpenFiles: 1000000
maxPods: 110
EOF生成kubeconfig文件
- 先写一个
kubelet-boot.sh
脚本 把下面的内容放进去
1 | cat > /opt/kubernetes/node/kubelet-boot.sh << EOF |
--embed-certs
为true
时表示将certificate-authority
证书写入到生成的bootstrap.kubeconfig
文件中;
设置客户端认证参数时没有指定秘钥和证书,后续由kube-apiserver
自动生成;
- 生成
kubelet-bootstrap.kubeconfig
文件(生成的kubelet-bootstrap.kubeconfig
文件放在配置文件目录中)1
2
3cd /opt/kubernetes/node/conf.d
sh /opt/kubernetes/node/kubelet-boot.sh
systemd管理kubelet
1
2
3
4
5
6
7
8
9
10
11
12
13
14cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
[Service]
EnvironmentFile=/opt/kubernetes/node/conf.d/kubelet.conf
ExecStart=/opt/kubernetes/node/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF启动并设置开机启动
1
2
3
4systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
systemctl status kubelet批准kubelet证书申请并加入集群
- 查看kubelet证书请求
kubectl get csr
- 批准申请
kubectl certificate approve name
- 建立一个 RBAC Role 来获取存取权限
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
35cat >> apiserver-to-kubelet-rbac.yml << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:k8s-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:k8s-apiserver
namespace: ""
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:k8s-apiserver-to-kubelet
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: k8s-apiserver
EOFname
为apiserver
证书的CN
字段;
- 应用
1
kubectl create -f apiserver-to-kubelet-rbac.yml
8.2 kube-proxy部署
创建配置文件
1
2
3
4
5
6cat > /opt/kubernetes/node/conf.d/kube-proxy.conf << EOF
KUBE_PROXY_OPTS="--config=/opt/kubernetes/node/conf.d/kube-proxy-config.yml \\
--log-dir=/opt/kubernetes/node/logs \\
--logtostderr=false \\
--v=2"
EOF配置参数文件
1
2
3
4
5
6
7
8
9
10cat > /opt/kubernetes/node/conf.d/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/node/conf.d/kube-proxy.kubeconfig
hostnameOverride: k8s-node1
clusterCIDR: 192.168.80.0/24
EOFPS: 需要修改
hostnameOverride
创建证书
- 查看 2.6 创建kube-proxy证书
拷贝证书
1
scp {kube-proxy.pem,kube-proxy-key.pem} k8s-master1:/opt/kubernetes/node/cert
生成
kubeconfig
文件
- 先写一个
kube-proxy-boot.sh
脚本 把下面的内容放进去
1 | cat > /opt/kubernetes/node/kube-proxy-boot.sh << EOF |
- 生成
1
2cd /opt/kubernetes/node/conf.d
sh /opt/kubernetes/node/kube-proxy-boot.sh
systemd管理kube-proxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14cat > /usr/lib/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=/opt/kubernetes/node/conf.d/kube-proxy.conf
ExecStart=/opt/kubernetes/node/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF启动并设置开机启动
1
2
3
4systemctl daemon-reload
systemctl start kube-proxy
systemctl enable kube-proxy
systemctl status kube-proxy
到此就已经把各组件服务部署完毕,接下来就是把各节点的服务补充部署上去,查看集群状态,排错等等
9. fannel网络组件部署
- 部署思路:
- 在node上下载cni依赖插件
- 在master上执行kube-flannel.yml
9.1 在kubelet中指定三个参数
这个本实例不需要,因为在部署kubelet的时候已经加了cni配置了
vim /opt/kubernetes/node/conf.d/kubelet.conf
1
2
3--network-plugin=cni : 网络插件使用cni
--cni-conf-dir=/etc/cni/net.d cni : 配置文件(默认)
--cni-bin-dir=/opt/cni/bin cni : 可执行文件(默认)
重启服务
1
systemctl restart kubelet && systemctl status kubelet
这样在
kublet
启动的时候,就会去/etc/cni/net.d
目录查找配置文件,并解析,使用相应的插件配置网络,因此之前node
会从Ready
变为NotReady
1
2
3
4[root@k8s-master1 logs]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-node1 NotReady <none> 22h v1.18.10
k8s-node2 NotReady <none> 22h v1.18.10
9.2 下载cni依赖插件
先准备好CNI二进制文件
下载地址解压二进制包并移动到默认工作目录
1
2mkdir /opt/cni/bin -p
tar xzvf cni-plugins-linux-amd64-v0.8.7.tgz -C /opt/cni/bin
9.3 flannel网络组件部署
在master上进行此步操作
- 下载yml文件
1
2
3cd /opt/cni/
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- 修改yml文件 - 子网,工作模式
此处的
network
配置要与Pod Network
(–service-cluster-ip-range)配置的一致
1 | net-conf.json: | |
Backend (工作模式)
Host-gw
: 同一网段直接通信,速度快udp
: 用户空间的udp封装vxlan
: 利用内核vxlan协议进行传输(推荐)aws vpc
: 利用aws平台内部提供的功能进行传输
- 修改网卡
目前需要在kube-flannel.yml中使用
- --iface
参数指定集群主机内网网卡的名称,否则可能会出现dns无法解析。
1 | command: |
- 准备镜像(目前不需要了)
- 这一步目前好像不需要了,国内对v13版本的镜像好像可以直接拉去,如果不行,则只能按下面步骤进行操作
在国内下载flannel镜像同样很容易失败,因此建议提前下载好,再去启动flannel DaemonSet,避免在启动过程中重试浪费时间。(如果能科学上网,则可以下来下载,然后再进行手动导入)(本实例使用自己导入的镜像)
国内flannel镜像获取查看:https://www.cnblogs.com/xiao987334176/p/12696740.html#autoid-6-1-0
下载flannel镜像
手动下载时镜像名称最好从kube-flannel.yml文件中拷贝,确保下载正确的镜像。
1
docker pull quay.io/coreos/flannel:v0.13.0
导入镜像 并 修改好导入的镜像名称,跟配置文件名称保持一致
1
2docker load -i quay.io-coreos-flannel_v0.13.0.tar.gz
docker tag e708f4bb69e3 quay.io/coreos/flannel:v0.13.01
2
3initContainers:
- name: install-cni
image: quay.io/coreos/flannel:v0.13.0 # 配置文件中
- 在master上运行
1
2kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-system
1 | kubectl get node |
10. Dashboard和CoreDNS部署
10.1 Dashboard部署
- 简介
在
Kubernetes
社区中,有一个很受欢迎的Dashboard
项目,它可以给用户提供一个可视化的 Web 界面来查看当前集群的各种信息。用户可以用Kubernetes Dashboard
部署容器化的应用、监控应用的状态、执行故障排查任务以及管理Kubernetes
各种资源。
- 相关地址
官方参考文档
- 当前部署dashboard版本:v2.0.3,注意检查dashboard版本与kubernetes版本兼容性:
https://github.com/kubernetes/dashboard/releases/tag/v2.0.3
下载yaml文件
1
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
修改yaml文件
- vim recommended.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17.....................
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
nodePort: 38443
type: NodePort
selector:
k8s-app: kubernetes-dashboard
.....................
创建
1
kubectl apply -f recommended.yaml
查看状态
1
2
3
4
5kubectl get pods,svc -n kubernetes-dashboard
kubectl get pods -n kubernetes-dashboard
kubectl get svc -n kubernetes-dashboard
- 登录dashboard
- 浏览器访问dashboard:
1
https://<any_node_ip>:38443
- Dashboard 支持 Kubeconfig 和 Token 两种认证方式,我们这里选择Token认证方式登录。
创建用户admin-user
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20cat > dashboard-adminuser.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOF创建
1
kubectl apply -f dashboard-adminuser.yaml
说明:上面创建了一个叫
admin-user
的服务账号,并放在kubernetes-dashboard
命名空间下,并将cluster-admin
角色绑定到admin-user
账户,这样admin-user
账户就有了管理员的权限。默认情况下,kubeadm
创建集群时已经创建了cluster-admin
角色,我们直接绑定即可。
- 查看admin-user账户的token
1
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
- 把token粘贴到登录窗口,然后登录
- 删除管理员
ServiceAccount
和ClusterRoleBinding
。1
2kubectl -n kubernetes-dashboard delete serviceaccount admin-user
kubectl -n kubernetes-dashboard delete clusterrolebinding admin-user
10.2 CoreDNS部署
下载官方yaml文件样板
1
2
3wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/coredns/coredns.yaml.base
cp coredns.yaml.base coredns.yaml修改yaml文件
70行:
__DNS__DOMAIN__
改为cluster.local
(这个值跟kubelet-config.yml
文件内的clusterDomain
值一致)139行:
__DNS__MEMORY__LIMIT__
改为160Mi
205行:
__DNS__SERVER__
改为192.168.80.2
(这个值跟kubelet-config.yml
文件内的clusterDNS
值一致)注释112-114行
1
2
3securityContext:
seccompProfile:
type: RuntimeDefault
- 修改镜像 135行 (下面是我上传到阿里镜像仓库的镜像)
1
registry.cn-hangzhou.aliyuncs.com/jeremy865/k8s-coredns:1.7.0
- 启动
1
kubectl apply -f coredns.yaml