环境准备
3 台虚拟机,IP 及 DNS 等配置已经配置好:
- 192.168.19.150 k8s-master01
- 192.168.19.160 k8s-node01
- 192.168.19.161 k8s-node02
以下操作如若没有特别说明,均在三台机器上执行!!!
更新 yum 源
# 3台虚拟机均更新 yum 源
yum update -y
设置系统主机名
# 在 master 节点上执行
hostnamectl set-hostname k8s-master01
# 在 node01 节点上执行
hostnamectl set-hostname k8s-node01
# 在 node02 节点上执行
hostnamectl set-hostname k8s-node02
Host 文件的相互解析
# 在 master 节点上修改 hosts 文件
vi /etc/hosts
# hosts 文件写入以下内容
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.19.150 k8s-master01
192.168.19.160 k8s-node01
192.168.19.161 k8s-node02
# 将 hosts 文件拷贝到 node01 和 node02 节点上
scp /etc/hosts root@k8s-node01:/etc/hosts
scp /etc/hosts root@k8s-node02:/etc/hosts
安装依赖包
yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget vim net-tools git
设置防火墙为 iptables 并设置空规则
# 关闭 firewalld
systemctl stop firewalld && systemctl disable firewalld
# 安装 iptables
yum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save
关闭 SELINUX
swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
调整内核参数
cat > kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1 # 开启网桥模式
net.bridge.bridge-nf-call-ip6tables=1 # 开启网桥模式
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1 # 关闭 ipv6
net.netfilter.nf_conntrack_max=2310720
EOF
# 开机加载
cp kubernetes.conf /etc/sysctl.d/kubernetes.conf
# 刷新配置
sysctl -p /etc/sysctl.d/kubernetes.conf
调整系统时区(可选)
# 设置系统时区为 中国/上海
timedatectl set-timezone Asia/Shanghai # 将当前的 UTC 时间写入硬件时钟timedatectl set-local-rtc 0# 重启依赖于系统时间的服务
systemctl restart rsyslog
systemctl restart crond
关闭系统不需要的邮件服务
# 关闭不需要的服务减少系统压力
systemctl stop postfix && systemctl disable postfix
设置 rsyslogd 和 systemd journald
CentOs7 以后,系统的引导方式改为了 systemd,这时会有两个日志系统同时工作,我们这里设置为 sysytemd journald 日志系统。
# 持久化保存日志的目录
mkdir /var/log/journal
mkdir /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-prophet.conf <<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent
# 压缩历史日志
Compress=yes
SyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=1000
# 最大占用空间 10G
SystemMaxUse=10G
# 单日志文件最大 200M
SystemMaxFileSize=200M
# 日志保存时间 2 周
MaxRetentionSec=2week
# 不将日志转发到 syslog
ForwardToSyslog=no
EOF
systemctl restart systemd-journald
升级系统内核为 4.44
CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker、Kubernetes 不稳定,例如: rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# 添加安装源
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# 安装完成后检查 /boot/grub2/grub.cfg 中对应内核 menuentry 中是否包含 initrd16 配置,如果没有,再安装一次!
yum --enablerepo=elrepo-kernel install -y kernel-lt
# 设置开机从新内核启动
grub2-set-default 'CentOS Linux (4.4.189-1.el7.elrepo.x86_64) 7 (Core)'
# 重启系统
reboot
# 查看当前系统内核版本
uanme -r
安装集群
kube-proxy 开启 ipvs 的前置条件
modprobe br_netfilter
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
安装 Docker
# 安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加 yum 源
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新缓存并安装 docker
sudo yum makecache fast && sudo yum -y install docker-ce
# 创建 /etc/docker 目录
mkdir /etc/docker
# 配置 daemon
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"registry-mirrors": [
"https://dockerhub.azk8s.cn",
"https://hub-mirror.c.163.com"
]
}
EOF
# 存放 docker 子配置文件
mkdir -p /etc/systemd/system/docker.service.d
# 重启 docker 服务
systemctl daemon-reload && systemctl restart docker && systemctl enable docker
安装 kubeadm(主从配置)
# 添加阿里云源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 安装
yum -y install kubeadm-1.15.1 kubectl-1.15.1 kubelet-1.15.1
# 开机自启(必须)
systemctl enable kubelet.service
导入镜像(可选)
kubeadm 初始化集群时会从 GCE(谷歌云) 下载相关镜像,由于网络原因,可以直接将下载好的镜像导入到三台机器中。
本人网盘分享:
链接:https://pan.baidu.com/s/1ZaZOfRsXJodMqRlQ-TsMAg
提取码:11in
# 将镜像导入到主节点 k8s-master01 机器的 /root/ 目录下
# 解压压缩包
tar -zxvf kubeadm-basic.images.tar.gz
# 解压后的文件夹名称为:kubeadm-basic.images
# 其中的镜像有:apiserver.tar coredns.tar etcd.tar kubec-con-man.tar pause.tar proxy.tar scheduler.tar
# /root 目录下写一个导入镜像脚本
vim load-images.sh
# 其内容如下
#!/bin/bash
ls /root/kubeadm-basic.images > /tmp/image-list.txt
cd /root/kubeadm-basic.images
for i in $( cat /tmp/image-list.txt )
do
docker load -i $i
done
rm -rf /tmp/image-list.txt
# 赋予脚本权限
chmod a+x load-images.sh
# 使用脚本导入镜像到docker
./load-images.sh
# 使用 scp 将镜像包以及导入脚本发送到 k8s-node01 和 k8s-node02
scp -r kubeadm-basic.images load-images.sh root@k8s-node01:/root
scp -r kubeadm-basic.images load-images.sh root@k8s-node01:/root
# 然后分别在 k8s-node01 和 k8s-node02 节点上执行脚本导入镜像到docker
初始化主节点
# 将 kubeadm 默认的初始化模板打印到 kubeadm-config.yaml 文件中(当前在 /root 目录下)
kubeadm config print init-defaults > kubeadm-config.yaml
# 修改配置文件
vim kubeadm-config.yaml
# 修改 localAPIEndpoint 下的 advertiseAddress 为 k8s-mmaster01 的IP
# 在 networking 下添加 podSubnet: "10.244.0.0/16"
# 在文件末位添加以下内容
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
SupportIPVSProxyMode: true
mode: ipvs
# 指定配置文件进行初始化; --experimental 自动颁发证书,在高可用环境有用;tee kubeadm-init.log 将日志打印到 kubeadm-init.log
kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs | tee kubeadm-init.log
错误解决:
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
若出现以上错误把虚拟机的处理器数量设置为 > 1即可。
初始化集群
我们使用 tee kubeadm-init.log
将日志输出到文件,后续可以从该文件中查看。
日志部分内容如下:
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[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 192.168.19.150:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:ca08a354d07d02a753cc6d05426efa8bcbdc05ecf6c0416cf825d07b5d2d50ce
日志中提示我们需要执行一些命令,我们提示执行命令即可:
# 在家目录下创建 .kube 文件夹
mkdir -p $HOME/.kube
# 将 kubectl 的连接配置文件放入 .kube 中
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# 授权
sudo chown $(id -u):$(id -g) $HOME/.kube/config
设置好之后我们就可以使用 kubectl
与 k8s
的 api server
进行交互了:
# 查看节点信息
kubectl get node
# 会输出以下信息,目前只有 k8s-master01 一个节点而且是 Notready 状态
NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady master 124m v1.15.1
因为 k8s 是需要一个扁平化网络环境的,当前还没有部署这个环境,所以节点状态是 Notready
。在部署 flannel
之后这个状态即可变为 Ready
。
部署 flannel
首先我们重新分配下与 k8s 部署相关的文件的存放路径:
新建目录 /root/install-k8s/core
将 /root
目录下的 kubeadm-config.yaml
kubeadm-init.log
kubernetes.conf
三个文件放置 /root/install-k8s/core/
目录下。
在 /root/install-k8s/
目录下新建 /plugin/flannel/
目录:
# 进入到 /root/install-k8s/plugin/flannel
# 下载 flannel 安装文件 kube-flannel.yml。如果使用 wget 不成功,可以使用其它方式下载,然后放置该目录
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 安装 flannel
kubectl create -f kube-flannel.yml
# 查看 flannel 状态。-n 指定命名空间,如果不加 -n 指定,默认是 default 的命名空间,而我们所以的组件都是安装在 kube-system 中
kubectl get pod -n kube-system
# 若 STATUS 为 Running 便是成功的:(状态为 Init:ImagePullBackOff 的排错方式在下方)
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-amd64-lchhp 0/1 Running 0 42s
# 此时再次查看 k8s-master01 状态,发现其状态是:Ready
kubectl get node
如果查看 flannel 的状态为 Init:ImagePullBackOff,可以使用以下命令查看具体错误:
kubectl describe pod kube-flannel-ds-amd64-lchhp -n kube-system
# 其最后显示信息包括:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7m55s default-scheduler Successfully assigned kube-system/kube-flannel-ds-amd64-lchhp to k8s-master01
Warning Failed 6m40s (x3 over 7m41s) kubelet, k8s-master01 Failed to pull image "quay.io/coreos/flannel:v0.12.0-amd64": rpc error: code = Unknown desc = Error response from daemon: Get https://quay.io/v2/: net/http: TLS handshake timeout
Normal Pulling 5m49s (x4 over 7m55s) kubelet, k8s-master01 Pulling image "quay.io/coreos/flannel:v0.12.0-amd64"
Warning Failed 5m18s (x4 over 7m41s) kubelet, k8s-master01 Error: ErrImagePull
Warning Failed 5m18s kubelet, k8s-master01 Failed to pull image "quay.io/coreos/flannel:v0.12.0-amd64": rpc error: code = Unknown desc = error pulling image configuration: Get https://d3uo42mtx6z2cr.cloudfront.net/sha256/4e/4e9f801d2217e98e94de72cefbcb010a7f2caccf03834dfd12a8e60abcaaecfd?Expires=1584512919&Signature=HZDYx8PPYv9qQWp8o8gtHYoXkP0FFIoQ9KevW-rWeoYw-JIcZa1fLdEOZuBaqtuQjIo~EanjmqiymRoSYYEOxNDa8euOc7L0QDXEGvCSYwYrWbIxJXpCkO7fc4lEW6tO8Hd83HkLxA4wnoPpYX5pTdke5pQCdIttDFHczZtO9HWFR3a1HSyS5kd4pwQTpUQ9UtYyCcAUUAIo-ZGPppurEkncuEL2OPvRjwKLrT6NV1SHEjrINqtgShNj9uoyw2ZzBnjRn2WWX2yXdBe1-sKFnCgYB3j7oV97L0nq5r1Vs2OyNloYGklewXMEcgV1d9gROGMvpwKbq~5c2wrphB4UMg__&Key-Pair-Id=APKAJ67PQLWGCSP66DGA: dial tcp: lookup d3uo42mtx6z2cr.cloudfront.net on 114.114.114.114:53: read udp 192.168.19.150:47547->114.114.114.114:53: i/o timeout
Normal BackOff 5m7s (x6 over 7m41s) kubelet, k8s-master01 Back-off pulling image "quay.io/coreos/flannel:v0.12.0-amd64"
Warning Failed 4m52s (x7 over 7m41s) kubelet, k8s-master01 Error: ImagePullBackOff
Warning Failed 2m44s kubelet, k8s-master01 Failed to pull image "quay.io/coreos/flannel:v0.12.0-amd64": rpc error: code = Unknown desc = context canceled
从错误信息中了解到 quay.io/coreos/flannel:v0.12.0-amd64
这个镜像拉取失败,此时有两种方式修改。
- 修改 kube-flannel.yml 文件中的镜像,换为其它镜像
- 拉取其他镜像,然后使用 tag 标记为
quay.io/coreos/flannel:v0.12.0-amd64
我这里使用的是 tag 标记
docker pull easzlab/flannel:v0.11.0-amd64
docker tag easzlab/flannel:v0.11.0-amd64 quay.io/coreos/flannel:v0.12.0-amd64
# 然后重新创建 flannel 即可
kubectl create -f kube-flannel.yml
将 k8s-node01 和 k8s-node02 加入集群
以上我们已经将 k8s-master01
节点成功部署,下面将 k8s-node01
和 k8s-node02
也加入集群中。
加入的命令在主节点初始化的日志中已经给我们了,我们直接将该命令分别在需要加入集群的机器上运行即可:
# 分别在 k8s-node01 和 k8s-node02 机器上运行
kubeadm join 192.168.19.150:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:ca08a354d07d02a753cc6d05426efa8bcbdc05ecf6c0416cf825d07b5d2d50ce
主要注意的是:
我们初始化主节点的时候,拉取 quay.io/coreos/flannel:v0.12.0-amd64
镜像可能会失败,因此在 k8s-node01
和 k8s-node02
上可以先行将该镜像准备好。具体方法在上面的排错中已经提到了。
执行完成后可以在 k8s-master01
节点上查看集群中的节点信息:
[root@k8s-master01 flannel]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready master 3h13m v1.15.1
k8s-node01 Ready <none> 68s v1.15.1
k8s-node02 Ready <none> 28s v1.15.1
至此,我们的集群环境已经搭建完成。
将 /root/install-k8s 文件夹放入 /usr/local/ 下,便于后续统一管理:
mv /root/install-k8s/ /usr/local/
-- end --