theboyaply
theboyaply
发布于 2020-03-18 / 1194 阅读
0
0

部署 k8s 集群

环境准备

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

设置好之后我们就可以使用 kubectlk8sapi 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-node01k8s-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-node01k8s-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 --


评论