准备
1.1 系统配置
准备两台机器,关闭防火墙(这里列举的node1为192.168.110.130,node2为131),
1 | cat /etc/hosts |
systemctl stop firewalld
或按照https://kubernetes.io/docs/setup/independent/install-kubeadm/说明,开放端口。
关闭selinux,然后reboot重启1
2
3setenforce 0 ---- 0关闭,1启用
vi /etc/selinux/config
SELINUX=disabled
创建/etc/sysctl.d/k8s.conf文件,添加如下内容:
1 | net.bridge.bridge-nf-call-ip6tables = 1 |
执行命令使修改生效。
1 | modprobe br_netfilter ----该指令用于向内核中加载/移除模块 |
1.2 kube-proxy开启ipvs的前置条件
kube-proxy是kubernetes重要的组件,它的作用是虚拟出一个VIP,保证VIP无论后台服务(pod,Endpoint)如何变更都保持不变,起到一个负载均衡的功能。
kube-proxty有三种模式ipvs、userspace、iptables三种,这里安装时使用ipvs模式(IP VirtualServer),所以需要为它加载以下的内核模块:
1 | ip_vs |
在所涉及的kubernetes节点(这里仅有node1,node2),执行以下脚本
1 | cat > /etc/sysconfig/modules/ipvs.modules <<EOF |
上述脚本创建了/etc/sysconfig/modules/ipvs.modules文件,保证在节点重启后能自动加载所需模块。 使用 lsmod | grep -e ip_vs -e nf_conntrack_ipv4命令,可以查看是否已经正确加载所需的内核模块。
另外,还需要确保各节点已经安装了ipset软件包(一般情况系统都已经自带了) yum install ipset,为了方便查看ipvs的代理规则,最好也安装一下管理工具ipvsadm,yum install ipvsadm。
如果以上前提条件不满足,则即使kube-proxy的配置开启了ipvs模式,也会退回到iptables模式。
1.3 安装docker
安装docker的yum源:(已安装过且版本匹配的可以跳过)
1 | yum install -y yum-utils device-mapper-persistent-data lvm2 |
查看最新的Docker版本:
1 | yum list docker-ce.x86_64 --showduplicates |sort -r |
Kubernetes 1.15当前支持的docker版本列表是1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09。 这里在各节点安装docker的18.09.7版本。
1 | yum makecache fast |
确认一下iptables filter表中FOWARD链的默认策略(pllicy)为ACCEPT。
1 | iptables -nvL |
如果有不匹配的,请使用 iptables -P FORWARD ACCEPT 修改过来
1.4 修改docker cgroup driver为systemd
根据文档CRI installation中的内容,对于使用systemd作为init system的Linux的发行版,使用systemd作为docker的cgroup driver可以确保服务器节点在资源紧张的情况更加稳定,因此这里修改各个节点上docker的cgroup driver为systemd。
创建或修改/etc/docker/daemon.json(这里很重要,错了就有坑):1
2
3
4
5cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
重启docker并设置开机启动(没有设置开机启动初始化时会失败):
1 | systemctl restart docker |
2 使用kubeadm部署kubernetes
2.1 安装kubeadm和kubelet
下面在各节点安装kubeadm和kubelet,这里涉及访问google,需要科学上网。(我试着找过阿里云镜像地址,但是并不能用……..)
1 | cat <<EOF > /etc/yum.repos.d/kubernetes.repo |
执行如下指令
1 | yum makecache fast |
从安装结果可以看出还安装了cri-tools, kubernetes-cni的依赖
Kubernetes 1.8开始要求关闭系统的Swap,如果不关闭,默认配置下kubelet将无法启动。 关闭系统的Swap方法如下:
1 | swapoff -a |
修改 /etc/fstab 文件,注释掉 SWAP 的自动挂载,使用free -m确认swap已经关闭。 swappiness参数调整,修改/etc/sysctl.d/k8s.conf添加下面一行:
1 | vm.swappiness=0 |
执行sysctl -p /etc/sysctl.d/k8s.conf使修改生效。
因为这里本次用于测试两台主机上还运行其他服务,关闭swap可能会对其他服务产生影响,所以这里修改kubelet的配置去掉这个限制。 使用kubelet的启动参数–fail-swap-on=false去掉必须关闭Swap的限制,修改/etc/sysconfig/kubelet,加入:
1 | KUBELET_EXTRA_ARGS=--fail-swap-on=false |
2.2 使用kubeadm init初始化集群
在各节点开机启动kubelet服务:
1 | systemctl enable kubelet.service |
使用kubeadm config print init-defaults可以打印集群初始化默认的使用的配置:
1 | apiVersion: kubeadm.k8s.io/v1beta2 |
从默认的配置中可以看到,可以使用imageRepository定制在集群初始化时拉取k8s所需镜像的地址。基于默认配置定制出本次使用kubeadm初始化集群所需的配置文件kubeadm.yaml(新建,任意位置下都行,advertiseAddress改成你的ip即可):
1 | apiVersion: kubeadm.k8s.io/v1beta2 |
在开始初始化集群之前可以使用kubeadm config images pull预先在各个节点上拉取所k8s需要的docker镜像。
接下来使用kubeadm初始化集群,选择node1作为Master Node,在node1上执行下面的命令:
1 | kubeadm init --config kubeadm.yaml --ignore-preflight-errors=Swap,NumCPU |
运行该指令时,kubernetes会检查环境是否符合要求,诸如cpu核心数不能小于2,我这里的虚拟机只分配了一个核心,所以–ignore-preflight-errors中加上了NumCPU忽略掉了,否则会启动不成功。
上面记录了完成的初始化输出的内容,根据输出的内容基本上可以看出手动初始化安装一个Kubernetes集群所需要的关键步骤。 其中有以下关键内容:
- [kubelet-start] 生成kubelet的配置文件”/var/lib/kubelet/config.yaml”
- [certs]生成相关的各种证书
- [kubeconfig]生成相关的kubeconfig文件
- [control-plane]使用/etc/kubernetes/manifests目录中的yaml文件创建apiserver、controller-manager、scheduler的静态pod
- [bootstraptoken]生成token记录下来,后边使用kubeadm join往集群中添加节点时会用到
下面的命令是配置常规用户如何使用kubectl访问集群:(这里必须执行,master和worker都需要)
1
2
3mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config最后给出了将节点加入集群的命令
1
2kubeadm join 192.168.110.130:6443 --token luxlja.y8td78jdh7immmfd \
--discovery-token-ca-cert-hash sha256:ab640c9f8a8497c23bb91454e4734a6642aaa3c6b622c0158a94a8b5ab29bb85
查看一下集群状态,确认个组件都处于healthy状态:
1 | kubectl get cs |
集群初始化如果遇到问题,可以使用下面的命令进行清理:(没问题的直接跳过)
1 | kubeadm reset |
2.3 安装Pod Network
接下来安装flannel network add-on:
1 | mkdir -p ~/k8s/ |
如果Node有多个网卡的话,需要修改kube-flannel.yml,为flanneld启动参数加上 –-iface=<iface-name>
(kubectl apply -f kube-flannel.yml对应安装flannel,同样的,如果安装出现问题需要重装,请使用kubectl delete -f kube-flannel.yml删除后再尝试。)1
2
3
4
5
6
7
8
9
10containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.11.0-amd64
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens33
......
检查master状态为Ready
1 | kubectl get nodes |
使用kubectl get pod –all-namespaces -o wide确保所有的Pod都处于Running状态。
(如果有其它状态的,请检查selinux关闭后需要重启)
1 | kubectl get pod -n kube-system |
2.4 测试集群DNS是否可用
1 | kubectl run curl --image=radial/busyboxplus:curl -it |
上述命令就是进入容器的意思,如果命令卡住了,尝试docker exec 该镜像也可以看到效果。进入容器后执行nslookup kubernetes.default确认解析正常:
1 | nslookup kubernetes.default |
2.5 向Kubernetes集群中添加Node节点
下面将node2这个主机添加到Kubernetes集群中(node2不需要执行kubeadm init),在node2上执行:
1 | kubeadm join 192.168.110.130:6443 --token luxlja.y8td78jdh7immmfd \ |
随后在node1节点上运行kubectl get nodes即可:
1 | kubectl get nodes |
2.6 kube-proxy开启ipvs
1 | kubectl edit cm kube-proxy -n kube-system |
找到如下部分的配置内容
1 | kind: KubeProxyConfiguration |
运行如下指令,会将之前的kube-proxy pod删除然后重新创建:
1 | kubectl get pod -n kube-system | grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}' |
查看新创建的kube-proxy:1
2
3
4
5kubectl get pod -n kube-system | grep kube-proxy
...
kube-proxy-7fsrg 1/1 Running 0 3s
kube-proxy-k8vhm 1/1 Running 0 9s
1 | kubectl logs kube-proxy-7fsrg -n kube-system |
日志中打印出了Using ipvs Proxier,说明ipvs模式已经开启。
3.移除节点
如果需要从集群中移除node2这个Node执行下面的命令:
在master节点上执行:
1 | kubectl drain node2 --delete-local-data --force --ignore-daemonsets |
在node2上执行:
1 | kubeadm reset |
在node1上执行:
1 | kubectl delete node node2 |