本系列文档将介绍使用二进制文件部署最新 kubernetes v1.14.2 集群所有步骤,而不是使用 kubeadm 等自动化方式来部署集群。主要适合于有一定 kubernetes 基础,想通过一步步部署的方式来学习和了解系统相关配置、运行原理的同学。也同样适用于测试或生产自建kubernetes集群等应用场景。
一 环境准备
1.1 版本信息:
-
OS 系统: Centos 7.6
-
kubernetes版本:v1.14.2
-
Etcd数据库:v3.3.13
-
Network插件:Flanneld 0.11.0
-
Docker 版本: 18.09.6-CE
-
K8s插件:CoreDns,Heapster,Influxdb,Grafana,Dashboard,elk,Metrics-server
- Docker仓库:Harbor
1.2 架构概览:
负载均衡:
采用keepalived主主模式结合haproxy tcp四层代理为kube apiserver提供高可用架构,内网使用内网VIP地址作为集群内所有组件访问地址;外网采用外网vip地址访问,主要为Internet 客户端访问
master集群:
使用keepalived+haproxy部署apiserver集群高可用;其他组件kube-controller-manager,kube-sheduler利用etcd选举机制,与apiserver组件部署同一node上,在分别部署了三个节点,组成高可用集群;
etcd集群:
同master节点所有组件部署在同一主机上,分别部署了三个节点,使用TLS开启HTTPS双向认证组成etcd高可用集群;
网络:
使用Flanneld打通master节点和node节点间网络,以便集群各个节点网络互通(亦可以使用calico网络);
客户端:
在devops机器上部署了kubectl以及kubens,其中kubectl主要是对kubernetes的object资源进行rest操作,kubens主要是用于ns切换
docker镜像仓库:
使用 vmware harboar作为docker私有镜像镜像;提供私有镜像pull,push,从而对私有的镜像进行管理
相关服务器信息如下图1所示:
主机名 | 内网IP | 外网IP | 服务器角色 | 部署软件或应用 |
---|---|---|---|---|
devops-k8s-n01 | 10.10.10.21 | 192.168.20.21 | 运维控制发布机 | kubectl, kubens, ansible, cffss |
lvs-ha-n01 | 10.10.10.30 | 192.168.20.30 | slb负载均衡器 | keepalived, haproxy, bind |
lvs-ha-n02 | 10.10.10.31 | 192.168.20.31 | slb负载均衡器 | keepalived, haproxy, bind |
master-k8s-n01 | 10.10.10.22 | 192.168.20.22 | master节点01 | master节点所有组件, flanneld插件 |
master-k8s-n02 | 10.10.10.23 | 192.168.20.23 | master节点02 | master节点相关组件, flanneld插件 |
master-ks8-n03 | 10.10.10.24 | 192.168.20.24 | master节点03 | master节点相关组件, flanneld插件 |
worker-k8s-n01 | 10.10.10.40 | 192.168.20.40 | worker节点01 | worker节点相关组件, flanneld插件 |
worker-k8s-n02 | 10.10.10.41 | 192.168.20.41 | worker节点02 | worker节点相关组件, flanneld插件 |
docker-hub-server | 10.10.10.20 | 192.168.20.20 | docker镜像仓库 | docker, docker-compose, harbor |
1.3. 组件访问策略
1.3.1 kube-apiserver:
-
基于Keepalived+ Haproxy 四层透明代理实现高可用;
-
开启非安全端口 8080 和关闭匿名访问,基于token访问;
-
在安全端口 6443 接收 https 请求;
-
严格的认证和授权策略 (x509、token、RBAC);
-
开启 bootstrap token 认证,支持 kubelet TLS bootstrapping;
- 使用 https 访问 kubelet、etcd,加密通信;
1.3.2 kube-controller-manager:
-
3 节点高可用;
-
开启安全端口,在安全端口 10252 接收 https 请求;
-
使用 kubeconfig 访问 apiserver 的安全端口;
-
自动 approve kubelet 证书签名请求 (CSR),证书过期后自动轮转;
- 各 controller 使用自己的 ServiceAccount 访问 apiserver;
1.3.3 kube-scheduler:
- 3 节点高可用;
- 使用 kubeconfig 访问 apiserver 的安全端口;
1.3.4 kubelet:
- 使用 kubeadm 动态创建 bootstrap token,而不是在 apiserver 中静态配置;
- 使用 TLS bootstrap 机制自动生成 client 和 server 证书,过期后自动轮转;
- 在 KubeletConfiguration 类型的 JSON 文件配置主要参数;
- 关闭只读端口,在安全端口 10250 接收 https 请求,对请求进行认证和授权,拒绝匿名访问和非授权访问;
- 使用 kubeconfig 访问 apiserver 的安全端口;
1.3.5 kube-proxy:
- 使用 kubeconfig 访问 apiserver 的安全端口;
- 在 KubeProxyConfiguration 类型的 JSON 文件配置主要参数;
- 使用 ipvs 代理模式;
二 系统基本设置
2.1 域名设置
在bind配置文件里添加以下解析记录,这里以mo9.com为 域名后缀,bind服务安装此处忽略。
解析A记录字段 | 域名后缀 | 解析IP | 备注 |
---|---|---|---|
lvs-ha-n01 | mo9.com | 10.10.10.30 | slb负载均衡器01,ssh主机使用 |
lvs-ha-n02 | mo9.com | 10.10.10.31 | slb负载均衡器 02,ssh主机使用 |
master-k8s-n01 | mo9.com | 10.10.10.22 | 设置master节点01域名以方便metric数据采集 |
master-k8s-n02 | mo9.com | 10.10.10.23 | 设置master节点02域名以方便metric数据采集 |
master-k8s-n03 | mo9.com | 10.10.10.24 | 设置master节点03域名以方便metric数据采集 |
worker-k8s-n01 | mo9.com | 10.10.10.40 | 设置worker 节点01域名以方便metric数据采集 |
worker-k8s-n02 | mo9.com | 10.10.10.41 | 设置worker 节点01域名以方便metric数据采集 |
registry-mirrors | mo9.com | 10.10.10.20 | docker镜像私有仓库域名,私有镜像上传下载使用 |
dev-kube-api | mo9.com | 10.10.10.100 | apiserver集群访问域名, 所有组件通过该域名访问apiserver |
dev-kube-api | mo9.com | 192.168.20.100 | apiserver集群外网访问域名, 外网用户通过该域名访问 |
备注:
这里需要要添加相关主机的域名解析,因为kubelet配置里hostname值是主机名时,不设置会导致dashboard上看不到pod日志输出error,提示无法机械节点域名;亦可以将该值设置成ip,避免无法访问10250端口服务,当然可以通过hosts方式将上述信息写到每个node上的/etc/hosts文件内
2.2 机器主机名设置及DNS解析地址设置
主机名设置
将对应主机hostname信息设置成表1信息所示的主机名
hostnamectl set-hostname 主机名
各node主机dns解析设置
在各个Linux主机上将对应DNS解析服务器地址设置成如下信息
search mo9.com
nameserver 10.10.10.30
nameserver 10.10.10.31
备注:
设置search mo9.com是为了方便当通过ssh + 主机名时可以直接登录,dashboard访问worker节点便于解析对应的主机采集数据
2.3 SSH免密登陆配置
所有操作均在 devops-k8s-n01节点上执行,通过ansible执行所有操作,所以需要添加devops机器到其它节点的ssh免密登陆,关于ssh密码登陆此处不介绍
注意:
由于的主机关于dns解析,主机名设置,ssh免密登陆等基本配置,以及内核参数基本优化,在各Linux主机创建时通过系统初始化已配置完成。所以这里不再阐述!
三 k8s各节点主机初始化
这里所有的操作命令需要在kubernetes集群内所有的主机上执行,是安装kubernetes集群环境所需要的基本设置。
3.1 安装相关依赖包
yum install -y epel-release conntrack ipvsadm \
ipset jq sysstat curl libseccomp ntpdate ntp wget telnet rsync
备注:
这里的依赖包主要是为worker节点上kubelet,kube-proxy,docker,以及网络插件组件安装依赖的安装包,其他包为基本网络测试包,建议在集群内所以机器上执行,因为flanneld插件需要这些依赖包
3.2 关闭防火墙
在每台机器上关闭防火墙,清理防火墙规则,设置默认转发策略:
systemctl stop firewalld >>/dev/null 2>&1
systemctl disable firewalld >>/dev/null 2>&1
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
iptables -P FORWARD ACCEPT
3.3 关闭 swap 分区
如果开启了 swap 分区,则worker节点上的kubelet 组件会启动失败(可以通过将参数 --fail-swap-on 设置为 false 来忽略 swap on),故需要在每台机器上关闭 swap 分区。同时注释 /etc/fstab 中相应的条目,防止开机自动挂载 swap 分区:
swapoff -a >>/dev/null 2>&1
sed -i 's/.*swap.*/#&/' /etc/fstab
3.4 关闭 SELinux
关闭 SELinux,否则后续 K8S 挂载目录时可能报错 Permission denied:
setenforce 0 >>/dev/null 2>&1
sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/sysconfig/selinux >>/dev/null 2>&1
sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config >>/dev/null 2>&1
sed -i "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/sysconfig/selinux >>/dev/null 2>&1
sed -i "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/selinux/config >>/dev/null 2>&1
3.5 关闭 dnsmasq(可选)
linux 系统开启了 dnsmasq 后(如 GUI 环境),将系统 DNS Server 设置为 127.0.0.1,这会导致 docker 容器无法解析域名,需要关闭它:
systemctl stop dnsmasq
systemctl disable dnsmasq
3.6 加载内核模块
主要是kube-proxy组件需要使用到ip_vs内核模块转发pods应用,实现endpoints路由;
sudo modprobe br_netfilter
sudo modprobe ip_vs
sudo modprobe ip_conntrack
3.7 优化内核参数
sudo sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf
sudo sed -i '/net.bridge.bridge-nf-call-iptables/d' /etc/sysctl.conf
sudo sed -i '/net.bridge.bridge-nf-call-ip6tables/d' /etc/sysctl.conf
sudo sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf
sudo sed -i '/net.ipv4.tcp_tw_recycle/d' /etc/sysctl.conf
sudo sed -i '/vm.swappiness/d' /etc/sysctl.conf
sudo sed -i '/vm.overcommit_memory/d' /etc/sysctl.conf
sudo sed -i '/vm.panic_on_oom/d' /etc/sysctl.conf
sudo sed -i '/fs.inotify.max_user_watches/d' /etc/sysctl.conf
sudo sed -i '/fs.file-max/d' /etc/sysctl.conf
sudo sed -i '/fs.nr_open/d' /etc/sysctl.conf
sudo sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf
sudo sed -i '/net.netfilter.nf_conntrack_max/d' /etc/sysctl.conf
cat >/etc/sysctl.d/kubernetes.conf<>/dev/null 2>&1
- sed操作主要是为了防止sysctl.conf配置与新增的内核参数冲突;
- 必须关闭 tcp_tw_recycle,否则和 NAT 冲突,会导致服务不通;
- 关闭 IPV6,防止触发 docker BUG;
3.8 设置系统时区
# 调整系统 TimeZone
timedatectl set-timezone Asia/Shanghai
# 将当前的 UTC 时间写入硬件时钟
timedatectl set-local-rtc 0
hwclock -w
# 更新服务时间
ntpdate ntp1.aliyun.com
# 重启依赖于系统时间的服务
systemctl restart rsyslog
systemctl restart crond
3.9 关闭无关的服务
systemctl stop postfix && systemctl disable postfix
3.10 设置 rsyslogd 和 systemd journald(可选)
systemd 的 journald 是 Centos 7 缺省的日志记录工具,它记录了所有系统、内核、Service Unit 的日志。相比 systemd,journald 记录的日志有如下优势:
- 可以记录到内存或文件系统;(默认记录到内存,对应的位置为 /run/log/jounal);
- 可以限制占用的磁盘空间、保证磁盘剩余空间;
- 可以限制日志文件大小、保存的时间;
- journald 默认将日志转发给 rsyslog,这会导致日志写了多份,/var/log/messages 中包含了太多无关日志,不方便后续查看,同时也影响系统性能。
mkdir /var/log/journal # 持久化保存日志的目录
mkdir /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-prophet.conf <
3.11 创建k8s服务运行用户及相关目录
创建k8s组件服务运行用户
groupadd k8s
useradd -g k8s /var/lib/k8s -c "Kubernetes Service" -m -s /sbin/nologin k8s
备注:kube-apiserver、controller-manager、scheduler、etcd为安全起见,使用k8s服务账号启动;但是所有的worker节点上组件以及相关网络组件因为需要使用root账号权限(如iptable设置)启动,因此worker节点上服务账号可以不创建!
创建k8s相关组件安装主目录以及证书存放目录
mkdir -p /data/apps/k8s && mkdir -p /etc/k8s/ssl
3.12 升级内核
CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker、Kubernetes 不稳定,例如:
- 高版本的 docker(1.13 以后) 启用了 3.10 kernel 实验支持的 kernel memory account 功能(无法关闭),当节点压力大如频繁启动和停止容器时会导致 cgroup memory leak;
- 网络设备引用计数泄漏,会导致类似于报错:"kernel:unregister_netdevice: waiting for eth0 to become free. Usage count = 1";
解决方案如下:
- 升级内核到 4.4.X 以上;
- 手动编译内核,disable CONFIG_MEMCG_KMEM 特性;
- 安装修复了该问题的 Docker 18.09.1 及以上的版本。但由于 kubelet 也会设置 kmem(它 vendor 了 runc),所以需要重新编译 kubelet 并指定 GOFLAGS="-tags=nokmem";
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
sudo grub2-set-default 0 >>/dev/null 2>&1
3.13 关闭 NUMA
# Disable numa for system.
sudo sed -i "s:numa=off::" /etc/sysconfig/grub
sudo sed -i "s:centos/swap rhgb:& numa=off:" /etc/sysconfig/grub
sudo grub2-mkconfig -o /boot/grub2/grub.cfg >>/dev/null 2>&1
4 控制机上安装ansible工具
由于所有操作都在devops机器上操作,为对所有机器进行命令操作,所有需要使用到ansible工具,将上述所有的命令根据服务器角色进行批量命令操作。
4.1 安装ansible工具
yum install ansible -y
4.2 根据服务器role创建ansible host文件进行分组
[master_k8s_vgs]
master-k8s-n01 ansible_host=10.10.10.22
master-k8s-n02 ansible_host=10.10.10.23
master-k8s-n03 ansible_host=10.10.10.24
[worker_k8s_vgs]
worker-k8s-n01 ansible_host=10.10.10.40
worker-k8s-n02 ansible_host=10.10.10.41
[slb_ha_vgs]
ha-lvs-n01 ansible_host=10.10.10.1
ha-lvs-n02 ansible_host=10.10.10.2
4.3 系统初始化设置
将上述系统优化
里所有的命令对master_k8s_vgs,worker_k8s_vgs两个组里所有服务器初始化操作,这里将上述命令编写成一个k8s初始化脚本并执行ansible script脚本model,命令如下:
ansible master_k8s_vgs -m script -a "/home/gamaxwin/install_k8s_setup.sh" -b
ansible worker_k8s_vgs -m script -a "/home/gamaxwin/install_k8s_setup.sh" -b
至此k8s内所有的节点系统初始化基本完成,出于集群的安全,还需要为k8s创建TLS双向认证证书,请参考第二小节:kubernetes集群安装指南:创建CA证书及相关组件证书密钥