下面是本次部署k8s集群的节点清单:
ip | hostname | cpu | memory | 角色 |
10.68.212.102 | node2 | 2c | 2g | work |
10.68.212.103 | node3 | 2c | 2g | work |
10.68.212.104 | node4 | 2c | 4g | master |
上面是笔者在笔记本电脑通过Oracle VM VirtualBox虚拟化出来的3个节点信息,资源配置较低,这里只是用来模拟生产环境的搭建,正常情况下生产环境每一个节点建议至少是2c4g或以上的配置。注意master角色节点强烈建议给够2c4g,哪怕是学习环境中,否则会由于资源不够的问题频繁重启容器导致整个集群引导启动失败,产生各种坑。
当前部署计划是根据k8s官方的架构将节点划分为master和work,master节点部署后初始化状态的集群运行以下组件:
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- etcd
- calico
下面是部署成功后master节点运行的Pod列表截图:
work节点部署后初始化状态的集群运行以下组件:
- kube-proxy
- kubelet
- calico
- 业务容器
k8s默认不会将业务Pod调度到集群控制面板所在的master节点,业务Pod只会被调度到work节点上,这点我们保持官方默认的配置不做修改。
安装Docker容器(所有节点)
k8s是管理容器的,所以要部署k8s前需要先安装好一款容器,这里选择Docker作为容器组件,这里假设你已经了解docker的使用,如果不了解docker那么请先登录docker官方网站或其它书籍学习好docker再来研究k8s,下面是安装docker的命令:
# 先卸载旧的docker:v19.03.8版本
yum remove docker \
docker-client \
docker-client-19.03.8 \
docker-common \
docker-19.03.8 \
docker-19.03.8-logrotate \
docker-logrotate \
docker-engine
# 安装yum-utils和docker依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加docker yum repo
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装docker-ce
yum update -y && yum install -y d.io-1.2.13 docker-ce-19.03.8 docker-ce-cli-19.03.8
# 配置/etc/docker/daemon.json
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
# 创建docker.service.d目录
mkdir -p /etc/systemd/system/docker.service.d
# 刷新system服务配置
systemctl daemon-reload
# 设置为开启启动,非必须
systemctl enable docker.service
# 启动docker
systemctl restart docker
# 查看docker服务启动状态,active为正常运行(绿色)
systemctl status docker
如果启动失败,可以查看系统日志文件: /var/log/messages。
安装kubeadm、kubelet、kubectl(所有节点)
1、确保每台机器配置为2c4g或以上。
2、确保机器节点网络能够互ping通。
根据hostname配置/etc/hosts文件,每个节点添加如下配置:
10.68.212.102 node2
10.68.212.103 node3
10.68.212.104 node4
3、确保节点之间hostname不重复,MAC地址或product_uuid不重复。
可以使用命令 ip link 或 ifconfig -a 来获取网络接口的 MAC 地址或通过 sudo cat /sys/class/dmi/id/product_uuid 命令查看 product_uuid 值是否有重复。
4、允许iptables查看桥接流量。
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
5、确保开放节点对应的端口,或简单粗暴直接关闭防火墙。
master节点防火墙规则:
协议 | 方向 | 端口范围 | 作用 | 使用者 |
TCP | 入站 | 6443* | k8s api服务器 | 所有组件 |
TCP | 入站 | 2379-2380 | etcd server client api | kube-apiserver, etcd |
TCP | 入站 | 10250 | kubelet api | kubelet 自身、控制平面组件 |
TCP | 入站 | 10251 | kube-scheduler | kube-scheduler 自身 |
TCP | 入站 | 10252 | kube-controller-manager | kube-controller-manager 自身 |
work节点防火墙规则:
协议 | 方向 | 端口范围 | 作用 | 使用者 |
TCP | 入站 | 10250 | k8s api服务器 | kubelet 自身、控制平面组件 |
TCP | 入站 | 30000-32767 | nodeport 服务 | 所有组件 |
或简单粗暴关闭防火墙命令(笔者就是这么干的):
# 设置开机不启动
systemctl disable firewalld
# 停止firewalld
systemctl stop firewalld
6、禁用交换区。
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#/g' /etc/fstab
sysctl -p
7、禁用SELinux。
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
8、时间同步。
yum install chrony -y
systemctl enable chronyd
systemctl start chronyd
chronyc sources
9、添加kubernate yum repo。
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=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
10、每个节点上安装kubeadm、kubelet、kubectl。
- kubeadm:用来引导启动集群的命令工具。
- kubelet:在集群中的每个节点上用来启动 pod 和容器等。
- kubectl:用来与集群通信的命令行工具。
# 指定安装1.18.0版本
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 –disableexcludes=kubernetes
注意这三个组件的安装版本必须配套才行,关于版本配套信息查阅下面文档连接:
https://kubernetes.io/docs/setup/release/version-skew-policy/
11、设置开机启动kubelet,非必须
systemctl enable kubelet.service
安装好k8s环境后先不启动,后面由kubeadm来引导启动集群。
通过kubeadm引导启动k8s集群(仅master节点执行)
该步骤仅在master节点执行,根据规划我们在node4节点上执行。
当k8s部署运行起来后便就是一个集群,哪怕只有一个节点。下面我们通过前面安装好的kubeadm命令工具来引导启动k8s集群,步骤如下:
1、查看引导集群时需要拉取的镜像
kubeadm config images list
从镜像中可以看到默认是从k8s.gcr.io仓库拉取,该仓库国内网络无法访问,在实际拉取时需要修改该仓库地址,除此之外还可以看到v1.18.0工具默认引导启动的集群版本为v1.18.2。
2、执行下面命令提前手工拉取对应的镜像(虽然默认会拉取,但是通常会超时失败,建议手工拉取):
kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers
通过--image-repository 指定一个仓库地址来替换默认的k8s.gcr.io,拉取完成后可以通过下面命令查看本地docker镜像列表:
docker images
3、通过下面命令引导启动集群:
kubeadm init --image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.18.2 \
--pod-network-cidr=192.168.0.0/16 \
--control-plane-endpoint=k8s-control-cluster-endpoint
--image-repository:指定拉取镜像仓库地址。
--kubernetes-version:指定引导启动的k8s版本。
--pod-network-cidr:指定pod网络插件的网络范围,不能与本地现有的网卡冲突。
--control-plane-endpoint:指定k8s控制面板共享端点,这对后面搭建k8s控制面板高可用时有用,值可以是后面的负载均衡器的DNS,这里暂时配置为node4的IP(所有节点都要配置):
vi /etc/hosts:
10.68.212.104 k8s-control-cluster-endpoint
看到如下输出,表示初始化控制面板成功并成功引导启动集群:
如果引导过程中失败,任何时候都可以通过/var/log/messages系统日志文件查看日志信息。
4、此时通过kubeadm命令引导k8s集群完毕,通过上面输出可以看到有这么一段话:
To start using your cluster, you need to run the following as a regular user:
........
大概意思是想要使用集群,还需要做点工作,如果你是非root用户,则需要执行下面命令:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
如果直接是root用户,那么则将下面环境变量配置到/etc/profile即可:、
export KUBECONFIG=/etc/kubernetes/admin.conf
# 使之生效
source /etc/profile
配置完毕后就可以正常使用kubectl命令来使用集群了。
5、上面截图中还有这么一句话:
You can now join any number of control-plane nodes by copying certificate authorities
........
大概意思是通过对应截图中下面kubeadm join命令可以将任意数量的控制面板节点加入到当前集群中,来实现控制面板的高可用。
6、上面截图中还有这么一句话:
Then you can join any number of worker nodes by running the following on each as root:
........
大概意思是通过对应截图中下面kubeadm join命令可以将任意数量的work节点加入到集群中,实现集群资源的扩展,这点后面会讲到,为了方便后面使用,应该把生成的该命令记录下来先:
kubeadm join k8s-control-cluster-endpoint:6443 --token 9r0x23.0prnupe7h1bjo17d \
--discovery-token-ca-cert-hash sha256:6433b5eec463c38954ee07e71b87026bf3f942f8df45f1782f17dd7efaabcbce
在该命令后面加上--control-plane也可以给第5点控制面板高可用使用,所以这里记录一次就可以了。
7、通过下面命令可以看到此时kubelet、apiserver、scheduler、etdc等master组件进程已经启动:
kubectl get pods --all-namespaces
我们注意到两个CoreDNS Pod状态为:Pending,这是因为没有安装部署Pod网络通信插件的原因,除此之外我们还可以通过下面命令查看当前集群的节点信息和状态:
kubectl get nodes
我们注意到此时集群只有一个节点node4,且状态时NotReady,代表不可用的状态,这也是因为没有安装部署Pod网络通信插件的原因,下面我们继续部署Pod网络通信插件。
安装部署Calico Pod网络插件(仅master节点执行)
该步骤仅在master节点执行,根据规划我们在node4节点上执行。
开源的Pod网络插件有很多,下面我们选择Calico作为网络插件部署,部署方式如下:
1、calico插件最终也是作为容器来运行,所以部署过程也会拉取相应的docker镜像,为了加速拉取镜像过程,我们需要配置下docker加速镜像(所有节点都要配置):
vi /etc/docker/daemon.json:
{
"registry-mirrors": [
"http://ovfftd6p.mirror.aliyuncs.com",
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com"
]
........
}
# 刷新配置并重启docker
systemctl daemon-reload
systemctl restart docker
2、通过下面命令部署Calico:
kubectl apply -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml
3、为了确保快速稳定运行Calico Pod,建议可以先拉取Calico对应的镜像,再执行第2步骤,通过浏览器回车访问上面的yaml文件地址:
https://docs.projectcalico.org/v3.14/manifests/calico.yaml
然后ctrl + f 搜索image关键字找到对应需要下载的镜像通过docker pull 来提前下载,例如笔者目前查看到的是下面的镜像:
docker pull calico/pod2daemon-flexvol:v3.14.0
docker pull calico/cni:v3.14.0
docker pull calico/kube-controllers:v3.14.0
docker pull calico/node:v3.14.0
拉取完毕镜像后然后再执行下面命令来部署calico:
kubectl apply -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml
4、等待一小段时间后,可以通过下面命令确定Calico已经成功运行:
kubectl get pods --all-namespaces
5、继续查看集群节点状态,此时已经从NetReady变为Ready:
kubectl get nodes
至此,集群引导基本完毕,如果我们需要重新引导集群则需要执行命令:kubeadm reset然后再执行上面的kubeadm init xxxxx命令即可。下面我们将其它work节点加入到集群中。
加入work节点到集群(work节点执行)
该步骤仅在work节点执行,根据规划我们在node2、node3节点上执行,并且确保在执行前work节点已经按照前面流程安装好了docker、kubeadm、kubectl、kubelet、docker等工作,并启动docker。
1、确保前面的hosts配置:
10.68.212.102 node2
10.68.212.103 node3
10.68.212.104 node4
10.68.212.104 k8s-control-cluster-endpoint
2、确保docker处于运行状态:
systemctl status docker
3、确保node2、node3节点都配置了docker加速镜像:
vi /etc/docker/daemon.json
{
"registry-mirrors": [
"http://ovfftd6p.mirror.aliyuncs.com",
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com"
]
........
}
systemctl daemon-reload
systemctl restart docker
4、提前手动拉取Calico镜像(虽然默认会拉取,但是通常会超时失败,建议手工拉取):
# work节点只需拉取这3个就可以了
docker pull calico/pod2daemon-flexvol:v3.14.0
docker pull calico/cni:v3.14.0
docker pull calico/node:v3.14.0
5、在node2、node3节点分别执行前面kubeadm init xxx输出的第二个join命令:
kubeadm join k8s-control-cluster-endpoint:6443 --token 9r0x23.0prnupe7h1bjo17d \
--discovery-token-ca-cert-hash sha256:6433b5eec463c38954ee07e71b87026bf3f942f8df45f1782f17dd7efaabcbce
看到如下输出证明加入成功:
6、此时回到master节点node4上执行如下命令确定工作节点是否成功加入:
kubectl get pods --all-namespaces
kubectl get nodes
至此,整个k8s集群部署完毕!
---------------------- 正文结束 ------------------------