谷粒商城-集群-82-K8S 集群搭建
一、基础环境搭建
1、前置要求
一台或多台机器,操作系统 CentOS7.x-86_x64
硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘 30GB或更多
集群中所有机器之间网络互通
可以访问外网,需要拉取镜像
禁止swap分区
2、部署步骤
- 1、在所有的节点上安装Docker和kubeadm
- 2、部署Kubernetes Master
- 3、部署容器网络插件
- 4、部署Kubernetes Node,将节点加入Kubernetes集群中
- 5、部署DashBoard web页面,可视化查看Kubernetes资源
3、环境准备
3.1、准备工作
我们可以使用 vagrant 快速创建三个虚拟机。虚拟机启动前先设置 virtualbox 的主机网络。现在全部统一为192.168.10.1
,以后所有虚拟机都是 10.x 的ip地址。
可以通过ifconfig命令查看我们宿主机的vboxnet0的IP:
> ifconfig
> vboxnet0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
ether 0a:00:27:00:00:00
inet 192.
169.168.10.1 netmask 0xffffff00 broadcast 192.168.10.255
Mac电脑的 virtualBox ->偏好设置->网络:
3.2、创建三台虚拟机
使用vagrant来快速的创建三台虚拟机,Vagrantfile文件:
Vagrant.configure("2") do |config|
(1..3).each do |i|
config.vm.define "k8s-node#{i}" do |node|
# 设置虚拟机的Box
node.vm.box = "centos/7"
# 设置虚拟机的主机名
node.vm.hostname="k8s-node#{i}"
# 设置虚拟机的IP,注意这里要替换为自己的IP
node.vm.network "private_network", ip: "192.168.10.#{99+i}", netmask: "255.255.255.0"
# 设置主机与虚拟机的共享目录
# node.vm.synced_folder "~/Documents/vagrant/share", "/home/vagrant/share"
# VirtaulBox相关配置
node.vm.provider "virtualbox" do |v|
# 设置虚拟机的名称
v.name = "k8s-node#{i}"
# 设置虚拟机的内存大小
v.memory = 4096
# 设置虚拟机的CPU个数
v.cpus = 4
end
end
end
end
将上边的文件放在 Vagrantfile
目录下 /Users/kaiyiwang/k8s
,然后进入该目录下启动 vagrant up
。
> cd /Users/kaiyiwang/k8s
> vagrant up
可以看到我们的三台虚拟机已经创建好了 ^_^,创建3台虚拟机不到 5 分钟,还是非常快速的:
3.3、设置密码登录
创建的虚拟机默认只允许 ssh 登录方式,为了后来方便操作,文件上传等,我们可以配置允许账号密码登录虚拟机,方便客户端 xshell
连接。
Vagrant ssh 进去系统之后
su root 密码为 vagrant # 切换为root用户
vi /etc/ssh/sshd_config
修改 PasswordAuthentication no/yes # 将 no改为yes
service sshd restart # 重启服务
具体操作,需要对这三台虚拟机都要修改:
➜ k8s vagrant ssh k8s-node1
[vagrant@k8s-node1 ~]$
修改完成后,我们可以通过 ip addr
命令查看这三台虚拟机对外访问的IP,这个虚拟机IP是我们在上边批量创建虚拟机的时候指定好的 192.168.10.#{99+i}
。
虚拟机名 | IP | 备注 |
---|---|---|
k8s-node1 | 192.168.10.100 | Text |
k8s-node2 | 192.168.10.101 | Text |
k8s-node3 | 192.168.10.102 | Text |
命令查看示例:
[root@k8s-node3 vagrant]# ip addr
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:27:22:85 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.102/24 brd 192.168.10.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe27:2285/64 scope link
valid_lft forever preferred_lft forever
配置好之后就可以用finalshell(mac)/xshell(windows) 进行SSH登录连接了。
FinalShell这个工具还是很强大的,在下边栏命令选择全部会话
,就会把命令直接发到我们这三台虚拟机上执行了,不用再一个一个来执行命令了,非常方便:
修改时区:
root@:~#
4、修改NAT网络
使用 ip route show
命令发现三台虚拟的网络IP是一样的10.0.2.15
,这样在后边集群处理的时候会有问题,所以,需要进行调整。
[vagrant@k8s-node3 ~]$ ip route show
default via 10.0.2.2 dev eth0 proto dhcp metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100
169.254.0.0/16 dev eth1 scope link metric 1003
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.102
关闭三台虚拟机,右键点击 k8s-node1 虚拟机,设置-》网络-》网卡,修改网络连接方式:
- 1、修改网络连接方式
网络地址转换(NAT)
为NAT网络
。 - 2、需要重新生成mac地址,之前旧的不能用。
其他两台虚拟机也按照上边的方法进行修改,这样改了之后,就成为真正的三台不同的虚拟机,每台虚拟机的IP和Mac地址都不同,完全是独立的访问。
然后再次查看链接的网卡IP,可以看到我们三台虚拟机的IP都不同了。
k8s-node1:
k8s-node2:
k8s-node3:
5、设置Linux环境(三个节点都执行)
# su root # 切换到root用户先
# 关闭防火墙
$ systemctl stop firewalld
$ systemctl disable firewalld
# 关闭 selinux
$ sed -i 's/enforcing/disabled/' /etc/selinux/config
$ setenforce 0
# 关闭内存交换
$ swapoff -a # 临时,只关当前会话的
$ sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久
$ free -g # 验证 swap 必须为 0
6、添加主机名与IP映射
默认的主机名与IP关系:
[vagrant@k8s-node1 ~]$ cat /etc/hosts
127.0.0.1 k8s-node1 k8s-node1
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
修改:
# 前边为网卡地址 后边为集群结点名
# 就如同Windows里边的host文件一样
$ vi /etc/hosts
# ip addr 命令查看 eth0网卡inet
10.0.2.15 k8s-node1
10.0.2.4 k8s-node2
10.0.2.5 k8s-node3
# 修改网络配置成静态ip,然后
service network restart
对三台虚拟机批量修改,改了之后三台虚拟机可以互相知道机器地址.
7、将桥接的IPv4流量传递到iptables链(三台批量修改)
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 重新加载
sysctl --system
这样可以精确的统计每台虚拟机的流量访问,为后边负载均衡做准备。
8、备份快照
前边我们已经做好了三台虚拟机的基本环境准备,为了防止后边出现问题,所以,需要备份系统,这里对三台虚拟机都快照。
二、k8s相关软件安装
Kubernetes 默认 CRI(容器运行时)为Docker,因此先安装Docker。
1、安装docker
1.1 卸载系统之前到docker
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
1.2 安装Docker-CE
# 安装必须的依赖
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 设置 docker repo 到 yum 位置
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 docker docker-cli
$ sudo yum install -y docker-ce docker-ce-cli containerd.io
基础环境准备好,可以给三个虚拟机备份一下,为 node3分配16g,剩下的3g,方便未来做测试,这里可根据自己机器配置来分配。
1.3 docker 加速
$ sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://22amdajy.mirror.aliyuncs.com"]
}
EOF
$ sudo systemctl daemon-reload # 重启docker的后台线程
$ sudo systemctl restart docker # 重启docker
$ sudo systemctl enable docker # 设置开机自启
2、安装kubeadm、kubelet和kubectl
2.1 添加阿里云kubernetes yum源
阿里云官方镜像:https://developer.aliyun.com/mirror/
CentOS / RHEL / Fedora
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
# yum install -y kubelet kubeadm kubectl # 这里默认是安装最新的,暂不执行,我们项目需要指定版本
# systemctl enable kubelet && systemctl start kubelet
2.2 安装指定版本
# yum list|grep kube # 检查yum源是否有kube相关的源
yum install -y kubelet-1.17.3 kubeadm-1.17.3 kubectl-1.17.3
说明:
- kubeadm —— 启动 k8s 集群的命令工具
- kubelet —— 集群容器内的命令工具
- kubectl —— 操作集群的命令工具
2.3 设置开机自启动
# 开机自启,kubelet是做代理的,把节点注册到集群中的,要跟集群通信,所以,开机必须自启动
systemctl enable kubelet
systemctl start kubelet # 启动
三、部署k8s-master
我们使用 k8s-node1
作为主机,以后管理我们所有的节点集群,为了方便管理和识别给 k8s-node1
改名为 k8s-node1(master)
。
1、master节点初始化
查看 master主机默认网卡地址
[vagrant@k8s-node1 ~]$ ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:1b:22:84 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic eth0
valid_lft 1104sec preferred_lft 1104sec
inet6 fe80::a00:27ff:fe1b:2284/64 scope link
valid_lft forever preferred_lft forever
可以看到我们master主机上的默认网卡地址为 10.0.2.15,所以,apiserver-advertise-address
地址就为该地址。
初始化(这个命令暂不执行,请继续往下看):
$ kubeadm init \
--apiserver-advertise-address=10.0.2.15 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version v1.17.3 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16
由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里指定阿里云镜像仓库地址。可以手动按照我们的 master_ images.sh
先拉取镜像,地址变为 registry.cn-hangzhou.aliyuncs.com/google_containers
也可以。
master_ images.sh
#!/bin/bash
images=(
kube-apiserver:v1.17.3
kube-proxy:v1.17.3
kube-controller-manager:v1.17.3
kube-scheduler:v1.17.3
coredns:1.6.5
etcd:3.4.3-0
pause:3.1
)
for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
# docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
done
将上边的文件上传到服务器,然后执行:
chmod +x master_images.sh # 修改文件可执行权限
sh ./master_images.sh
执行上边的命令后,就下载了我们需要的镜像了。
下载好了镜像之后,再执行上边的初始化命令,如果没有先下载好镜像初始化命令可能会运行好久出错了也不好找:
$ kubeadm init \
--apiserver-advertise-address=10.0.2.15 --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version v1.17.3 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16
提示:如果上边找不到kubeadm命令,可以直接使用
/usr/bin/kubeadm
绝对路径
在初始化时,出现了端口占用问题:
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR Port-6443]: Port 6443 is in use
[ERROR Port-10259]: Port 10259 is in use
[ERROR Port-10257]: Port 10257 is in use
[ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
杀进程没用,最终重启一下kubeadm就可以了,如下:
[root@k8s-node1 vagrant]# kubeadm reset
# systemctl daemon-reload && systemctl restart kubelet
然后重新执行上边的初始化命令,就可以看到初始化成功了,初始化很复杂,需要大概执行4分钟多
又出现了这样的错误:
[kubelet-check] Initial timeout of 40s passed.
Unfortunately, an error has occurred:
timed out waiting for the condition
This error is likely caused by:
- The kubelet is not running
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
- 'systemctl status kubelet'
- 'journalctl -xeu kubelet'
Additionally, a control plane component may have crashed or exited when started by the container runtime.
To troubleshoot, list all containers using your preferred container runtimes CLI, e.g. docker.
Here is one example how you may list all Kubernetes containers running in docker:
- 'docker ps -a | grep kube | grep -v pause'
Once you have found the failing container, you can inspect its logs with:
- 'docker logs CONTAINERID'
error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
To see the stack trace of this error execute with --v=5 or higher
Unable to fetch the kubeadm-config ConfigMap from cluster: failed to get config map: Get https://10.0.2.15:6443/api/v1/namespaces/kube-system/configmaps/kubeadm-config?timeout=10s: dial tcp 10.0.2.15:6443: connect: connection refused
[root@k8s-node1 vagrant]# kubectl get cs
The connection to the server localhost:8080 was refused - did you specify the right host or port?
# netstat -ntlp 查看监听的端口,是否有监听8080
查看日志:
journalctl -xeu kubelet > kub.log # 将日志输入到 kub.log
cat kub.log # 查看日志
Sep 19 14:50:23 k8s-node1 kubelet[11174]: E0919 14:50:23.839320 11174 kubelet.go:2183] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
这里是个巨坑,在这里卡了一天,看起来是cni初始化的问题,原因:因为kubelet配置了network-plugin=cni,但是还没安装,所以状态会是NotReady,不想看这个报错或者不需要网络,就可以修改kubelet配置文件,去掉network-plugin=cni 就可以了。
https://github.com/kubernetes/kubernetes/issues/48798
[root@k8s-node1 etc]# find / -name 10-kubeadm.conf
/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
[root@k8s-node1 kubelet.service.d]# cat 10-kubeadm.conf
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
去掉 network-plugin=cni
这个参数:
[root@k8s-node1 vagrant]# cat /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--cgroup-driver=cgroupfs --network-plugin=cni --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.1"
[root@k8s-node1 vagrant]#
我靠,折腾了大半天,上边的方法还是没用,网上找了各种资料,心灰意冷时试了一下第二台虚拟机 k8s-node2
, 结果在这台虚拟机执行成功了,可能是第一台虚拟机环境有问题导致的,不过都是一起装的,应该没问题才对,郁闷啊。。。
再次执行:
[root@k8s-node1 vagrant]#
kubeadm init --apiserver-advertise-address=10.0.2.15 --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --kubernetes-version v1.17.3 --service-cidr=10.96.0.0/16 --pod-network-cidr=10.244.0.0/16 --v=5
# --v=5 打印执行步骤日志,方便排查问题
addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.0.2.4:6443 --token 9ynlak.9aqy7s13j1fqk2cy \
--discovery-token-ca-cert-hash sha256:251d64a3e79b3a8bd0f7ebea7385819c3357732059b49d6e2d5776e8e7897d4c
[root@k8s-node2 home]# cd
需要把上边执行完的结果复制保存下来,后边需要用。
2、测试kubectl(主节点执行)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
获取所有节点:
[root@k8s-node2 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-node2 NotReady master 8h v1.17.3
目前master节点是 notReady
状态,等待网络加入完成即可。
$ journalctl -u kubelet #日志
3、安装Pod网络插件(CNI)
kubectl apply -f \
https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
以上地址可能被墙,可以获取已经下载好的 kube-flannel.yml 运行即可。
wget yml 的本地下载地址:
wget https://digtime-k8s.oss-cn-heyuan.aliyuncs.com/k8s/kube-flannel.yml
同时 kube-flannel.yml
中指定的images 访问不到可以去 docker hub 找一个。
vi 修改 yml 所有 amd64 的地址都修改了即可。
等待大约 3 分钟
将上述文件下载到服务器,然后执行:
[root@k8s-node2 k8s]# kubectl apply -f kube-flannel.yml
执行完之后,查看命名空间:
# kubectl get ns # 查看节点
kubectl get pods -n kube-system # 查看指定名称空间的pods
kubectl get pods --all-namespaces # 查看所有名称空间的pods
所有的名称空间pods:
[root@k8s-node2 vagrant]# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7f9c544f75-cn79t 1/1 Running 1 13h
kube-system coredns-7f9c544f75-wzsb8 1/1 Running 1 13h
kube-system etcd-k8s-node2 1/1 Running 2 13h
kube-system kube-apiserver-k8s-node2 1/1 Running 2 13h
kube-system kube-controller-manager-k8s-node2 1/1 Running 2 13h
kube-system kube-flannel-ds-amd64-f2gk7 1/1 Running 1 4h53m
kube-system kube-proxy-hcg8n 1/1 Running 2 13h
kube-system kube-scheduler-k8s-node2 1/1 Running 2 13h
4、其他节点加入到主节点
其他节点要加入到主节点,需要使用初始化生成的 kubeadmin join
,不过这个Token一般两个小时内有效,如果超过有效期未加入,则需要重新生成。
kubeadm join 10.0.2.4:6443 --token 9ynlak.9aqy7s13j1fqk2cy \
--discovery-token-ca-cert-hash sha256:251d64a3e79b3a8bd0f7ebea7385819c3357732059b49d6e2d5776e8e7897d4c
Token过期处理方法:
kubeadm token create --print-join-command # 生成的Token有效期为两个小时
kubeadm token create --ttl 0 --print-join-command # --ttl0 该参数表示生成的Token永久有效
就是用上边的命令重新生成永久的Token:
[root@k8s-node2 k8s]# kubeadm token create --ttl 0 --print-join-command
W0920 07:34:34.715042 13730 validation.go:28] Cannot validate kubelet config - no validator is available
W0920 07:34:34.715104 13730 validation.go:28] Cannot validate kube-proxy config - no validator is available
kubeadm join 10.0.2.4:6443 --token snnpap.44slpcxoxqe0wxm6 --discovery-token-ca-cert-hash sha256:251d64a3e79b3a8bd0f7ebea7385819c3357732059b49d6e2d5776e8e7897d4c
将 k8s-node3
节点加入到集群中,在k8s-node3
虚拟机运行上边生成的命令:
kubeadm join 10.0.2.4:6443 --token snnpap.44slpcxoxqe0wxm6 --discovery-token-ca-cert-hash sha256:251d64a3e79b3a8bd0f7ebea7385819c3357732059b49d6e2d5776e8e7897d4c
打印结果:
在主节点可以看到 k8s-node3 节点已经加入进来了。
kubectl get nodes
节点监控:
$ watch kubectl get pod -n kube-system -o wide
5、对k8s-node1虚拟机的修复
之前这台虚拟机节点死活都连接不上,不知道哪里出了问题,今天对这台机器的Mac地址重新生成了一下,然后再次试了下,居然神奇的可以了。
之前这台机器的eth0 地址是: 10.0.2.5,重新生成Mac地址后新的地址是: 10.0.2.6,可能之前的Mac地址有问题。
然后也将我们这台虚拟机加入到集群中,然后在 主节点打印已加入的节点:
[root@k8s-node2 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-node1 NotReady <none> 12s v1.17.3
k8s-node2 Ready master 15h v1.17.3
k8s-node3 NotReady <none> 85m v1.17.3
可以看到我们创建的三台虚拟机都已经加入到了集群中,k8s-node2为master主节点,k8s-node1和k8s-node3为从节点。
折腾了两天总算把k8s集群的环境搭建好了^_^
相关文章:
安装笔记K8S 1.15.0版本遇到的一些错误汇总(部分参考网络上经验,基本可以解决问题)
kubernetes配置网络插件flannel
谷粒商城-集群-82-K8S 集群搭建
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)