k8s 集群部署ansible方式
一、集群配置与分布
IP | Hostname | Role | CPU | Memory |
---|---|---|---|---|
10.0.43.71 | k8s-m1 | master | 2 | 16G |
10.0.43.72 | k8s-m2 | master | 2 | 16G |
10.0.43.73 | k8s-m3 | master | 2 | 16G |
10.0.43.74 | k8s-n1 | worker | 2 | 16G |
二、安装准备
2.1 准备工作
- 升级centos7内核
- 配置集群免密登录
# 更改主机名(集群所有机器)
[root@k8s-m1 ~]# hostnamectl set-hostname k8s-m1
[root@k8s-m1 ~]# vi /etc/hosts
[root@k8s-m1 Kubernetes-ansible]# vi /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1 k8s-m1
10.0.43.71 k8s-m1
10.0.43.72 k8s-m2
10.0.43.73 k8s-m3
10.0.43.74 k8s-m4
# 配置ssh免密登录(3台)
[root@k8s-m1 ~]# ssh-keygen -t rsa
# 主节点
[root@k8s-m1 ~]# cd .ssh
[root@k8s-m1 .ssh]# ls
id_rsa id_rsa.pub
[root@k8s-m1 .ssh]# cat id_rsa.pub >> authorized_keys
# 从节点
[root@k8s-m2 ~]# ssh-copy-id -i k8s-m1
[root@k8s-m3 ~]# ssh-copy-id -i k8s-m1
[root@k8s-n1 ~]# ssh-copy-id -i k8s-m1
# 主节点
[root@k8s-m1 ~]# chmod 600 .ssh/authorized_keys
[root@k8s-m1 ~]# scp /root/.ssh/authorized_keys k8s-m2:/root/.ssh/
[root@k8s-m1 ~]# scp /root/.ssh/authorized_keys k8s-m3:/root/.ssh/
[root@k8s-m1 ~]# scp /root/.ssh/authorized_keys k8s-n1:/root/.ssh/
测试免密登录
2.2 下载脚本(主节点中某一台)
yum install -y git && \
git clone --recurse-submodules https://github.com/zhangguanzhang/Kubernetes-ansible.git -b v1.13
进入脚本目录
[root@k8s-m1 ~]# cd Kubernetes-ansible
[root@k8s-m1 Kubernetes-ansible]# vi inventory/hosts
为脚本运行改配置
修改inventory/hosts
inventory
目录存放了简单的example可以参考下,这里介绍下一些其他场景。- 如果master的机器网卡名不一样可以下面这样写
INTERFACE_NAME
[etcd]
不写的话默认在master的每个成员上部署,etcd的名字请写clusterName
- 如果机器系统准备好的时候就设置了hostname则删掉
hostname=xxx
的部分
[master]
10.0.43.71 hostname=k8s-m1 nodename=10.0.43.71 clusterName=etcd-001
10.0.43.72 hostname=k8s-m2 nodename=10.0.43.72 clusterName=etcd-002
10.0.43.73 hostname=k8s-m3 nodename=10.0.43.73 clusterName=etcd-003
[node]
10.0.43.74 hostname=k8s-n1 nodename=10.0.43.74
#172.16.1.7 hostname=k8s-n2 nodename=172.16.1.7
如果每台机器密码不一样参照inventory/hosts
最下面那样写
修改group_vars/all.yml
这里介绍一些可能需要修改的字段
-
ansible_ssh_pass
为ansible基于ssh的密码 -
VIP
为HA的vip -
certSANs
是证书里的域名和预留ip,默认的不要动,只能新加 -
nodeStatusUpdate
见 https://github.com/zhangguanzhang/Kubernetes-ansible/wiki/nodeStatusUpdate -
KUBE_VERSION
和ETCD_version
是给ds的yaml用,二进制需要改版本的话改下载脚本而不是这里,以及这俩变量用来判断渲染一些yaml文件 -
flanneld.type
如果不是云上而是在自己的机房或者虚拟化虚机跑, 可以把vxlan
模式改成host-gw
模式 -
如果未来会部署多套集群,pod和svc的cidr最好要提前分配下不要整成默认的10.96和10.244,可能未来会把两个集群的pod整成互通,关于cidr不要乱写,例如
10.95.0.0/12
实际上是在10.80.0.0/12
的范围里,不会确定可以在线找个cidr计算下 -
某些用户例如三台机器都是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写
安装ansible
[root@k8s-m1 Kubernetes-ansible]# bash scripts/Install-ansible.sh
离线安装ansible的话可以在页面找最新版本 https://releases.ansible.com/ansible/rpm/release/epel-7-x86_64/, 把rpm包先下载下来用yum解决依赖
yum install wget -y 1 > /dev/null
wget https://releases.ansible.com/ansible/rpm/release/epel-7-x86_64/ansible-2.8.5-1.el7.ans.noarch.rpm
yum localinstall ansible-2.8.5-1.el7.ans.noarch.rpm -y
测试ansible是否可达机器
[root@k8s-m1 Kubernetes-ansible]# ansible all -m ping
10.0.43.74 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.43.71 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.43.73 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.43.72 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
三、k8s集群安装
3.1 谨慎用法
在Kubernetes-ansible
目录里
01-setup.yml
# 运行
[root@k8s-m1 Kubernetes-ansible]# ansible-playbook 01-setup.yml
该步骤会设置基础设置+安装时间同步并重启生效,有些系统自带dnsmasq
,这里出现Could not find rhe request service dnsmasq
忽略。喜欢测试最新内核的人可以带上-e 'kernel=true'
会升级到最新的内核。
执行完后再连上去在剧本目录运行ansible all -m shell -a date
看看连通性和时间是否一致,时间不一致则检查chrony服务
02-docker.yml
# 运行
[root@k8s-m1 Kubernetes-ansible]# ansible-playbook 02-docker.yml
根据group_vars/all.yml
里docker.version
从aliyun使用yum模块安装docker-ce,如果出现错误可以再来一次,单独为某个节点安装可以运行ansible-playbook 02-docker.yml -e 'run=172.16.1.10'
,这个也可以为非k8s以外的机器安装docker。如果机器的docker服务在运行会不安装docker,仅仅配置配置+重启,想强制升级带上'-e force=true'
1.14-1.15,<1.16.3的版本使用19.03.3以下docker且cg驱动为systemd因为runc报错耗cpu和内存,该bug在19.03.3+修复,如果是低版本的docker,可以升级docker后再升级下containerd.io
版本
# 不需运行
$ rpm -qa | grep containerd.io
containerd.io-1.2.10-3.2.el7.x86_64
03-get-binaries.sh
[root@k8s-m1 Kubernetes-ansible]# bash 03-get-binaries.sh all
- 这步不是剧本,手动运行
bash 03-get-binaries.sh all
: 通过docker下载k8s和etcd的二进制文件还有cni插件,觉得不信任可以自己其他方式下载。 - cni压缩包放剧本目录,二进制文件放/usr/local/bin/
- 如果是运行剧本机器不是第一个master节点,可以利用上面02的
-e 'run=localhost'
安装完docker后运行此步下载 - 想下载同大版本内的小版本号则更改脚本里的版本号
04-tls.yml
运行ansible-playbook 04-tls.yml
生成证书和管理组件的kubeconfig,kubeconfig生成依赖kubectl命令,此步确保已经下载有kubectl.
05-etcd.yml
运行ansible-playbook 05-etcd.yml
06-HA.yml
运行ansible-playbook 06-HA.yml
keepalived+haproxy, haproxy七层去check apiserver, 四层代理+VIP来高可用 https://zhangguanzhang.github.io/2019/03/11/k8s-ha/
07-master.yml
运行ansible-playbook 07-master.yml
[root@k8s-m1 Kubernetes-ansible]# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-1 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
08-bootstrap.yml
运行ansible-playbook 08-bootstrap.yml
生成bootstrap文件给kubelet注册用
09-node.yml
运行ansible-playbook 09-node.yml
kubelet,执行完后看看kubectl get node
有没有(notReady为正常),没有就debug,如何debug见 https://github.com/zhangguanzhang/Kubernetes-ansible/wiki/systemctl-running-debug
10-addon.yml
运行ansible-playbook 10-addon.yml
此步部署kube-proxy,flannel,coredns,metrics-server。如果flannel二进制跑请运行前下载二进制文件bash 03-get-binaries.sh flanneld
,daemonset的话提前拉取镜像使用命令拉取ansible Allnode -m shell -a 'curl -s https://zhangguanzhang.github.io/bash/pull.sh | bash -s -- quay.io/coreos/flannel:v0.11.0-amd64'
, flanneld错误的话请把debug的错误信息提交到issue里
3.2 勇者部署(与3.1任选一种)
- 运行完01和02以及
03-get-binaries.sh
后执行ansible-playbook deploy.yml
3.3 给机器打role
kubectl label node node_ip node-role.kubernetes.io/master=master
kubectl label node node_ip node-role.kubernetes.io/node=worker
# 测试
[root@k8s-m1 Kubernetes-ansible]# kubectl label node 10.0.43.71 node-role.kubernetes.io/master=master
node/10.0.43.71 labeled
[root@k8s-m1 Kubernetes-ansible]# kubectl label node 10.0.43.72 node-role.kubernetes.io/master=master
node/10.0.43.72 labeled
[root@k8s-m1 Kubernetes-ansible]# kubectl label node 10.0.43.73 node-role.kubernetes.io/master=master
node/10.0.43.73 labeled
[root@k8s-m1 Kubernetes-ansible]# kubectl label node 10.0.43.74 node-role.kubernetes.io/worker=worker
node/10.0.43.74 labeled
[root@k8s-m1 Kubernetes-ansible]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
10.0.43.71 Ready master 2m38s v1.13.12
10.0.43.72 Ready master 2m39s v1.13.12
10.0.43.73 Ready master 2m39s v1.13.12
10.0.43.74 Ready node,worker 2m39s v1.13.12
3.4 添加node
- 在当前的ansible目录改hosts,添加[newNode]分组写上成员和信息,role是复用的,所以不要在此时修改一些标志位参数,例如flanneld.type和bin
- 执行
ansible-playbook setup.yml -e 'run=newNode'
, 然后等待重启完可以ping通后执行ansible-playbook addNode.yml
- 然后查看是否添加上
四、k8s中部署nginx测试
[root@master0 mgc]# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
[root@master0 mgc]# cat nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: NodePort
ports:
- port: 8000
targetPort: 80
nodePort: 31111
selector:
app: nginx
[root@k8s-m1 k8s-nginx]# ls
nginx-deploy.yaml nginx-svc.yaml
[root@k8s-m1 k8s-nginx]# kubectl apply -f nginx-svc.yaml
service/nginx created
[root@k8s-m1 k8s-nginx]# kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx created
[root@k8s-m1 k8s-nginx]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-7db75b8b78-6km6h 0/1 ContainerCreating 0 29s
nginx-7db75b8b78-x92lt 0/1 ContainerCreating 0 29s
五、问题
对于无法通过节点ip、服务ip、虚拟VIP访问的问题,解决如下
# 所有节点执行
sed -ri 's#"ipvs"#"iptables"#' /etc/kubernetes/kube-proxy.conf
# 所有节点,修改配置文件
[root@k8s-m1 nginx]# vi /lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
ExecStart=/usr/local/bin/kube-proxy \
--hostname-override=10.0.43.71 \
--logtostderr=false \
--log-dir=/var/log/kubernetes/kube-proxy \
# 增加ipvx配置
--proxy-mode=ipvs \
# 指定配置文件
--kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig \
--v=2
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
# 重启
systemctl daemon-reload && systemctl restart kube-proxy
六、部署可视化监控工具kuboard
安装
kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml
查看kuboard运行状态
[root@k8s-m1 nginx]# kubectl get pods -l k8s.eip.work/name=kuboard -n kube-system
NAME READY STATUS RESTARTS AGE
kuboard-6b86c9757b-dn8rm 1/1 Running 0 69s
获取管理员token
[root@k8s-m1 nginx]# kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d
eyJhbGciOiJFUzUxMiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJvYXJkLXVzZXItdG9rZW4tYjI4aDIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoia3Vib2FyZC11c2VyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMWJjNzI1M2MtOTM2Yi0xMWVhLTlmMDAtMGNkYTQxMWQ3ZTQ4Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmt1Ym9hcmQtdXNlciJ9.AbGjx3zSoAeECge5J5RRLRyMl_U6KyA9MRGJ9CukbwxEWaeJv-QkhH39vFCsHpmWrzfPY-Whau2NNXJfohYtA9fcAP0iokMJRu2h_i9Ftx7cSa0jBN9jsUCIqq0EKxjmzis4C-DY_qX0H4yXzDiagF21baHbAquz3e86KmgJdKIZVm25
访问
http://任意一个Worker节点的IP地址:32567/