-
Notifications
You must be signed in to change notification settings - Fork 201
写给公司同事看的部署步骤
这套ansible的大体步骤都是kubeadm的执行步骤抠出来按照标准来实现,cs的三个管理组件以及node上的kube-proxy
和cni
(目前使用的是flannel)都不使用staticPod和ds来部署。因为 kubeadm 的 join 和 init 都是取默认路由 bind 在多网卡下会有问题,因为生产环境都是多网卡,减少不必要的 bind 不能写0.0.0.0
。
写到现在大体的逻辑都写完了,后续都是更新细节性的问题。涉及到kind:APIService
这个资源对象的反向代理,master上需要运行cni(flannel,calico)以及kubelet,不想master调度pod可以加污点
系统尽量采用centos7的最新版本(7.4和7.4以下使用docker会出现很多莫名奇妙的问题),下面文章都会以centos上做说明。ubuntu不熟悉,但是如果你(看完后)对步骤的目的都熟悉了后可以自己为ubuntu写一套
- 配置最低建议2c4g,这个值来源于kubeadm的配置checks
- 静态ip配置,多网卡就做bond,bond名最好都一样,如果部署机器是底层openstack网络下的虚机的话,由于k8s的HA是基于VIP实现的高可用,默认ip和mac绑定会导致VIP无法外部通信,需要解绑ip和mac,见文章 基于openstack的ecs上使用vip
- dns改成内网的dns或者不是纯内网环境则使用公网的,确保
/etc/resolv.conf
里没有nameserver 127.0.0.x
和search
的行 - 如果纯内网则要准备一个ntp server,因为集群是tls的时间误差会认证失败
准备文件可以自己提前下载了,涉及到docker镜像的部分可以自己拉取离线save。主要思想是部署,要清楚每一步的目的是干啥,如果我写的步骤不适合当前的场景,你有更好的实现手段(甚至不使用ansible)能达到相同目的的话可以完全使用你的喜好。如果想完全离线的话,要注意以下这几个部分:
- ansible依赖,可以rpm包解决
- 系统一些包的基础依赖 --- 内网镜像仓库
- docker这部分 --- 可以镜像阿里云的repo,或者二进制包+systemd(这样的话得改ansible)
- docker镜像 --- 要么把相关docker镜像save成tar包,但是这样镜像被gc掉了会很麻烦,推荐提前推送到内网的docker镜像仓库上。
- k8s相关的二进制文件可以提前准备好
cd
yum install -y git && \
git clone --recurse-submodules https://github.com/zhangguanzhang/Kubernetes-ansible.git \
-b v1.16
cd Kubernetes-ansible
k8s版本号为vx.y.z
,一般我们叫vx.y
版本,例如v1.16
,这个属于大版本。同一个大版本内配置全部是兼容的,只修复功能性的bug问题,不会新增功能,不同大版本(cs和node相关的)配置文件会有细微性的差距(所以kubeadm为了避免这个都是保留最小能运行的参数,这样不符合我们的预期),所以我仓库按照大版本来做分支名。-b后面接需要安装的版本
因为各个版本直接差异性主要是k8s管理组件,所以我ansible的很多文件都是采用git submodules来复用
对于版本选择,不要盲目追求新的。如果最新版本的小版本号小于4就使用上一个大版本的最后一个版本,像之前v1.14
弄错了内核模块名字,v1.18
的ipvs模块错误。如果是升级集群最好要对各种k8s的kind:xxx
和apiVersion
都调查下是否废弃或者并入到其他api组或者字段变化。
- 安装ansible,需要外网,离线则使用rpm包 https://releases.ansible.com/ansible/rpm/release/epel-7-x86_64/
bash scripts/Install-ansible.sh
- 修改
group_vars/all.yml
里ssh的密码
ansible_ssh_pass: 'zhangguanzhang'
- 修改
inventory/hosts
该目录里还有其他的情况的示例,如果hostname
已经设置了就删掉hostname=xxx
。下面例子是三个master也做node的内容
# kubelet's node name must be `[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*`
# nodename used by k8s cluster, you also could use the ip address
# nodename to k8s, clusterName to etcd
[master]
172.16.1.3 hostname=k8s-m1 nodename=172.16.1.3 clusterName=etcd-001
172.16.1.4 hostname=k8s-m2 nodename=172.16.1.4 clusterName=etcd-002
172.16.1.5 hostname=k8s-m3 nodename=172.16.1.5 clusterName=etcd-003
#[newMaster]
#172.16.1.12 hostname=k8s-m4 nodename=k8s-m4
[Master:children]
master
[Allnode:children]
Master
#如果各台密码和端口不通请按照下面格式填写好并注释掉group_vars/all.yml里的ansible_ssh_pass的那一行
#172.16.1.13 ansible_ssh_pass=password ansible_ssh_port=666
#172.16.1.14 ansible_ssh_pass=password233 ansible_ssh_port=68
- 使用ping模块测试下ansible可达主机否,pong则可达
ansible all -m ping
!!!!!主要是运行ansible的剧本,全部得在clone下来的文件根目录里,也就是目录Kubernetes-ansible
里运行后面的剧本和ansible命令!!!!!!!!!。
按照系统标准(很多非运维的人改主文件而不是子配置文件,有对应daemon程序但是去写rc.local等)来设置系统和配置参数,以及安装k8s的少部分依赖和后续运维时候的一些工具
编辑文件group_vars/all.yml
,如果内网则使用内网的ntp server
ntp_servers:
- 'cn.pool.ntp.org'
- 's1b.time.edu.cn'
kernel: !!bool false # 这个是内核升级,默认为false。如果想自己尝试新内核可以试试,前提你得对配置启动内核和相关知识有一定了解下才建议设置成 true
运行
ansible-playbook 01-setup.yml
根据docker的检查脚本centos要配置一个user namespace的内核参数,所以此步执行完了会重启。如果出现不ok的,例如yum直连公网安装一些依赖会没成功,假如三台,有台172.16.1.2
没成功执行完。等运行ansible的机器正常重启上来后单独继续执行
ansible-playbook 01-setup.yml -e run=172.16.1.2
全部机器ok后利用shell模块看下连通性和时间是否一致,不一致则检查chrony服务
ansible all -m shell -a date
此步是添加aliyun的docker-ce
源,根据docker的官方安装脚本逻辑里抠出来的步骤,官方脚本里只有直连或者使用阿里云的源选项。以及设置docker补全脚本和修正FORWARD
链
编辑文件group_vars/all.yml
docker:
version: '19.03' # docker版本,如果要各个环境严格一致得写全版本号,例如`19.03.8`
# Environments:
# - HTTP_PROXY=http://127.0.0.1:8080 # 有docker使用代理拉镜像需求的话
dataDir: /var/lib/docker # 有条件这个目录单独分个区
execOpts:
- 'native.cgroupdriver=systemd'
registryMirrors: # 公网的一些镜像源
- https://fz5yth0r.mirror.aliyuncs.com
- https://dockerhub.mirrors.nwafu.edu.cn
- https://docker.mirrors.ustc.edu.cn/
- https://reg-mirror.qiniu.com
- http://hub-mirror.c.163.com/
- https://registry.docker-cn.com
# 内网harbor之类的镜像仓库,可以按照格式填写
# insecureRegistries:
# - 100.64.2.52:9999
# - 100.64.1.31:9999
运行
ansible-playbook 02-docker.yml
出现某个节点docker安装失败的则单独尝试
ansible-playbook 02-docker.yml -e run=172.16.1.2
如果有私有仓库,可能需要下面步骤,先每个机器登录私网仓库,不知道就询问公司的相关人员登录信息
docker login harbor-local.unicloudsrv.com -u '$username' -p '$password'
我有用travis-ci
的runner来把k8s的相关文件压缩包做成docker镜像推送到dockerhub上,此步是pull 相关镜像,然后run起来后docker cp出相关文件。相关文件有:
- k8s压缩包,cp出来后解压到
/usr/local/bin/
- cni plugins包,用于ansible分发到各个node上的
/opt/cni/bin/
- docker cp出镜像的etcd二进制文件,flannel二进制文件
如果你要整离线则可以看脚本加载的那些下载方法和路径,也可以改03-get-binaries.sh
里版本号来下载同一个大版本内前面或者后面的小版本。
运行,dockerhub可能会很久才拉去下来。
bash 03-get-binaries.sh all
这步生成很多步骤的证书和kubeconfig,依赖openssl
和kubectl
,kubectl是上一步下载的。这步的证书具体信息有兴趣可以看我博客 https://zhangguanzhang.github.io/2019/03/03/kubernetes-1-13-4/#%E5%BB%BA%E7%AB%8B%E9%9B%86%E7%BE%A4CA-keys-%E4%B8%8ECertificates
运行
ansible-playbook 04-tls.yml
二进制使用systemd管理部署etcd,配置文件按照etcd的github仓库的yaml配置示例文件,而不是写systemd里的命令行参数,etcd的参数值也可以环境变量。此步不会开启v2的etcd api,因为现在k8s都是用v3 api存储,v2和v3共存会无法恢复备份
同时生成alias脚本/etc/profile.d/etcd.sh
,可以使用etcd_v3
别名来操作集群。同时会生成定时备份脚本在crontab里
有需要就编辑文件group_vars/all.yml
etcd:
dataDir: /var/lib/etcd # 数据文件目录
initialClusterToken: 'etcd-k8s-cluster' # 写个字符串
backup:
dataDir: /opt/etcd_bak # 备份目录
scriptDir: /etc/etcd/ # 备份脚本存放目录
count: "4" # 最大保留几个备份
运行
ansible-playbook 05-etcd.yml
查看集群状态
source /etc/profile.d/etcd.sh # 只有这次需要source,后续都不用source
etcd-ha # 这个别名命令查看集群信息,默认etcd都会部署在master上
下面是输出
+-------------------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-------------------------+------------------+---------+---------+-----------+-----------+------------+
| https://172.16.1.3:2379 | a7aaefdac178d910 | 3.3.18 | 10 MB | false | 179 | 5492243 |
| https://172.16.1.4:2379 | bd8b8913565899ce | 3.3.18 | 9.9 MB | false | 179 | 5492243 |
| https://172.16.1.5:2379 | 5b602b26bf6b6050 | 3.3.18 | 10 MB | true | 179 | 5492243 |
+-------------------------+------------------+---------+---------+-----------+-----------+------------+
keepalived+haproxy, haproxy在apiserver的web七层/healthz
路由去check, 四层代理+VIP来高可用。 原理见 https://zhangguanzhang.github.io/2019/03/11/k8s-ha/
如果是openstack的虚机,记得解绑ip和mac的绑定,否则vip无法外部通信
有需要就编辑文件group_vars/all.yml
VIP: '172.16.1.240' # 选同一个掩码网络下未被使用的ip即可,可以提前ping下看看使用了没有
VIP_NETMASK: 24 # 网络的掩码
INTERFACE_NAME: eth0 # vip应该在哪张网卡上,如果有做bond则写bond的名,单网卡就网卡的名
运行
ansible-playbook 06-HA.yml
运行完在没有vip的机器上ping下vip地址看icmp可达不
master的三个管理组件
有需要就编辑文件group_vars/all.yml
# 下面前三个要改就一起改
SvcCIDR: 10.96.0.0/12
KubernetesClusterSVCIP: 10.96.0.1 # 默认占据SVC段的第一个ip,用于证书里SAN值
ClusterDns: 10.96.0.10 #修改SvcCIDR的画确保它的ip在CIDR内
PodCIDR: 10.244.0.0/16 # pod的ip的cidr
ServiceNodePortRange: 30000-32767 # nodePort的范围
ClusterDomain: cluster.local # 如果不懂这个作用就不要修改
运行
ansible-playbook 07-master.yml
查看状态,v1.16目前到在get cs显示unkown是官方废弃的, 不影响使用。废弃后在大家呼吁下又在1.17版本回来了,非1.16版本cs是有status的
$ kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-2 Healthy {"health": "true"}
etcd-1 Healthy {"health": "true"}
etcd-0 Healthy {"health": "true"}
bootstrap用于注册和扩展node 运行
ansible-playbook 08-bootstrap.yml
配置和启动kubelet
有需要就编辑文件group_vars/all.yml
,infra_image如果离线则改成内网镜像仓库上的镜像
infra_image: 'zhangguanzhang/pause-amd64:3.2'
私有镜像的话会有个bug,私有镜像则提前docker login登录内网镜像仓库,然后运行拉取下镜像ansible all -m shell -a 'docker pull xxx/xxxx/pause-amd64:3.2'
运行
ansible-playbook 09-node.yml
稍等一会儿后查看node,notReady
为正常,因为此时还未部署cni(剧本里是flannel)。如果一致啥都没输出则debug kubelet,见 systemctl debug
kubectl get node
kube-proxy在kubelet后部署,然后再是cni(热门的是calico和flannel),coredns为集群内部提供dns服务,metrics-server是kubectl top命令信息来源提供。
有需要就编辑文件group_vars/all.yml
,如果是云下物理机或者解绑了ip和mac的虚机,推荐把vxlan
改成host-gw
flanneld:
img: quay.io/coreos/flannel:v0.11.0-amd64 # 不重要
bin: !!bool true # 不懂就不要改,默认二进制运行flannel
type: vxlan # or set the value to 'host-gw' 如果是云下物理机或者解绑了ip和mac的虚机,推荐使用host-gw
healthzPort: 8471
# logDir: /var/log/flanneld # 新版无`log_dir参数`,详情 https://github.com/coreos/flannel/issues/1115
logLevel: 2
三台机器都是master+node,没有纯node,想在ipvs模式下从VIP:nodePort
去访问集群暴露的服务的话, 记得VIP_NETMASK
改成32,原因见 https://github.com/kubernetes/kubernetes/issues/75443 ,不改掩码的话也可以配置roles/CoreAddons/templates/kube-proxy.conf.j2
指定bind范围,文件尾部添加下面内容
nodePortAddresses:
- 172.16.1.0/24 #根据实际cidr写
如果把这里的coredns和metrics-server使用内网镜像则需要创建k8s的imagePullSecret
,给默认和kube-system俩ns创建并给sa patch下
kubectl create secret docker-registry harbor-local \
--docker-server=harbor-local.unicloudsrv.com \
--docker-username=xxxx \
--docker-password=xxxxx
kubectl patch serviceaccount default \
-p '{"imagePullSecrets": [{"name": "harbor-local"}]}'
kubectl -n kube-system create secret docker-registry harbor-local \
--docker-server=harbor-local.unicloudsrv.com \
--docker-username=xxxx \
--docker-password=xxxxx
kubectl -n kube-system serviceaccount default \
-p '{"imagePullSecrets": [{"name": "harbor-local"}]}'
pause镜像使用私有仓库的则有个bug,见 https://github.com/kubernetes/kubernetes/issues/90503 推荐把这个镜像放到内网仓库一个公开的repo里 运行
ansible-playbook 10-addon.yml
等镜像拉取
kubectl -n kube-system get po -o wide
确保coredns的pod running了后,测试下
time curl -I 10.96.0.10:9153/metrics
如果是real 1m3
秒的话请查看文章 https://zhangguanzhang.github.io/2020/05/23/k8s-vxlan-63-timeout/ 或者使用v1.18.6, v1.16.13, v1.17.9
以上的kube-proxy试下