• 本文所使用的镜像文件都在这里 附件.zip,如果怕麻烦,只需要在安装 docker 之后,使用 docker load -i xxx.tar 命令,将镜像文件的压缩包导入到 Docker 中。
  • 当然,也可以使用 for name in $(ls); do docker load -i $name;done命令批量导入,前提是需要进入到存放镜像的那个目录。

第一章:环境规划

1.1 集群类型

  • Kubernetes 集群大致分为两类:一主多从和多主多从。
    • 一主多从(单 master ):一个 Master 节点和多台 Node 节点,搭建简单,但是有单机故障风险,适合用于测试环境。
    • 多主多从(高可用):多台 Master 节点和多台 Node 节点,搭建麻烦,安全性高,适合用于生产环境。
  • 单 master 的架构图:

1.png

  • 高可用集群的架构图:

2.png

3.png

为了测试方便,本次搭建的是一主多从类型的集群。

1.2 安装方式

  • Kubernetes 有多种部署方式,目前主流的方式有 kubeadm 、minikube 、二进制包。
  • ① minikube:一个用于快速搭建单节点的 Kubernetes 工具。
  • ② kubeadm:一个用于快速搭建Kubernetes 集群的工具(可以用于生产环境)。
  • ③ 二进制包:从官网上下载每个组件的二进制包,依次去安装(建议生产环境使用)。

1.3 主机规划

角色 IP地址 操作系统 配置 hostname
Master 192.168.68.100 CentOS 7.9,基础设施服务器 2核CPU,4G内存,50G硬盘 k8s-master
Node1 192.168.68.101 CentOS 7.9,基础设施服务器 2核CPU,4G内存,50G硬盘 k8s-node1
Node2 192.168.68.102 CentOS 7.9,基础设施服务器 2核CPU,4G内存,50G硬盘 k8s-node2

1.4 搭建流程

  • ① 准备 3 台机器,要求网络互通(如果是云服务器,要求私网互通;如果是虚拟机,要求网络互通)。
  • ② 在 3 台机器上安装 Docker 容器化环境。
  • ③ 安装 Kubernetes :
    • 3 台机器安装核心组件:kubeadm(创建集群的引导工具)、kubelet 、kubectl(程序员使用的命令行)。
    • kubelet 可以直接通过容器化的方式创建出 Kubernetes 的核心组件,如:Controller Manager、Scheduler 等。
    • 由 kubeadm 引导创建 Kubernetes 集群。

第二章:Kubernetes 安装(v1.21)

2.1 Kubernetes 和 Docker 之间的版本对应关系

2.png

从文档中,我们可以知道 Docker 的版本是 v20.10 ,对应的 Kubernetes 的版本是 v1.21 。

2.2 前置条件

  • 如果是虚拟机则需要让三台机器互通,最简单的做法就是关闭防火墙。
  1. systemctl stop firewalld
  1. systemctl disable firewalld

3.gif

  • 如果是云厂商提供的云服务器则需要让三台机器的私有 IP 互通,不懂的,请查看《云平台操作》,而且还需要设置安全组策略放行指定的端口。
  • ① Master 节点: | 协议 | 方向 | 端口范围 | 目的 | 使用者 | | —- | —- | —- | —- | —- | | TCP | 入站 | 6443 | Kubernetes API server | 所有 | | TCP | 入站 | 2379-2380 | etcd server client API | kube-apiserver, etcd | | TCP | 入站 | 10250 | Kubelet API | 自身, 控制面 | | TCP | 入站 | 10259 | kube-scheduler | 自身 | | TCP | 入站 | 10257 | kube-controller-manager | 自身 |
  • ② Node 节点: | 协议 | 方向 | 端口范围 | 目的 | 使用者 | | —- | —- | —- | —- | —- | | TCP | 入站 | 10250 | Kubelet API | 自身, 控制面 | | TCP | 入站 | 30000-32767 | NodePort Services† | 所有 |
  • 目前,青云(云厂商)除了以上的操作之外,还需要设置安全组的组内互信。

4.png

5.png

6.png

2.3 准备工作

2.3.1 升级系统内核

  • 查看当前系统的版本:
  1. cat /etc/redhat-release

7.gif

  • 查看当前系统的内核:
  1. uname -sr

8.gif

默认的 3.10.0 实在是太低了。

  • 在 CentOS 7.x 上启用 ELRepo 仓库:
  1. rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
  1. rpm -Uvh https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm

9.gif

  • 查看可用的系统内核相关包:
  1. yum --disablerepo="*" --enablerepo="elrepo-kernel" list available

10.gif

  • 安装最新主线内核版本:
  1. yum -y --enablerepo=elrepo-kernel install kernel-ml

11.gif

  • 设置默认的内核版本:
  1. vim /etc/default/grub
  1. GRUB_TIMEOUT=5
  2. GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
  3. GRUB_DEFAULT=0 # 修改此处,原来是 saved
  4. GRUB_DISABLE_SUBMENU=true
  5. GRUB_TERMINAL_OUTPUT="console"
  6. GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"
  7. GRUB_DISABLE_RECOVERY="true"

12.gif

  • 重新创建内核配置:
  1. grub2-mkconfig -o /boot/grub2/grub.cfg

13.gif

  • 重启系统:
  1. reboot

14.gif

  • 查看当前系统的内核:
  1. uname -sr

15.gif

2.3.2 设置主机名

  • 命令:
  1. hostnamectl set-hostname <hostname>
  • 示例:
  1. # 192.168.65.100
  2. hostnamectl set-hostname k8s-master
  1. # 192.168.65.101
  2. hostnamectl set-hostname k8s-node1
  1. # 192.168.65.102
  2. hostnamectl set-hostname k8s-node2

16.gif

2.3.3 主机名解析

  • 为了方便后面集群节点间的直接调用,需要配置一下主机名解析,企业中推荐使用内部的 DNS 服务器。
  1. cat >> /etc/hosts << EOF
  2. 127.0.0.1 $(hostname)
  3. 192.168.65.100 k8s-master
  4. 192.168.65.101 k8s-node1
  5. 192.168.65.102 k8s-node2
  6. EOF

17.gif

2.3.4 时间同步

  • Kubernetes 要求集群中的节点时间必须精确一致,所以在每个节点上添加时间同步:
  1. yum install ntpdate -y
  1. ntpdate time.windows.com

18.gif

2.3.5 关闭 SELinux

  • 查看 SELinux 是否开启:
  1. getenforce
  • 永久关闭 SELinux ,需要重启:
  1. sed -i 's/enforcing/disabled/' /etc/selinux/config
  • 关闭当前会话的 SELinux ,重启之后无效:
  1. setenforce 0

19.gif

2.3.6 关闭 swap 分区

  • 永久关闭 swap ,需要重启:
  1. sed -ri 's/.*swap.*/#&/' /etc/fstab
  • 关闭当前会话的 swap ,重启之后无效:
  1. swapoff -a

20.gif

2.3.7 将桥接的 IPv4 流量传递到 iptables 的链

  • 修改 /etc/sysctl.conf 文件:
  1. # 如果有配置,则修改
  2. sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.conf
  3. sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g" /etc/sysctl.conf
  4. sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.conf
  5. sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf
  6. sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf
  7. sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf
  8. sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g" /etc/sysctl.conf
  1. # 可能没有,追加
  2. echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
  3. echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
  4. echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
  5. echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
  6. echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
  7. echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
  8. echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
  • 加载 br_netfilter 模块:
  1. modprobe br_netfilter
  • 持久化修改(保留配置包本地文件,重启系统或服务进程仍然有效):
  1. sysctl -p

21.gif

2.3.8 开启 ipvs

  • 在 Kubernetes 中 service 有两种代理模型,一种是基于 iptables ,另一种是基于 ipvs 的。ipvs 的性能要高于 iptables 的,但是如果要使用它,需要手动载入 ipvs 模块。
  • 在三台机器安装 ipset 和 ipvsadm :
  1. yum -y install ipset ipvsadm
  • 在三台机器执行如下脚本:
  1. cat > /etc/sysconfig/modules/ipvs.modules <<EOF
  2. #!/bin/bash
  3. modprobe -- ip_vs
  4. modprobe -- ip_vs_rr
  5. modprobe -- ip_vs_wrr
  6. modprobe -- ip_vs_sh
  7. modprobe -- nf_conntrack
  8. EOF
  • 授权、运行、检查是否加载:
  1. chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4

22.gif

2.3.9 重启

  • 重启三台机器:
  1. reboot

23.gif

2.3.10 Docker 安装

  • 三台机器上都安装 Docker 。
  • 卸载旧版本:
  1. sudo yum remove docker \
  2. docker-client \
  3. docker-client-latest \
  4. docker-common \
  5. docker-latest \
  6. docker-latest-logrotate \
  7. docker-logrotate \
  8. docker-engine

24.gif

  • yum 安装 gcc 相关:
  1. yum -y install gcc
  1. yum -y install gcc-c++

25.gif

  • 安装所需要的软件包:
  1. yum -y install yum-utils

26.gif

  • 设置 stable 镜像仓库:
  1. yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

27.gif

  • 更新 yum 软件包索引:
  1. yum makecache fast

28.gif

  • 查看存储库中 Docker 的版本:
  1. yum list docker-ce --showduplicates | sort -r

29.gif

  • 安装指定版本的 Docker(v20.10) :
  1. yum -y install docker-ce-3:20.10.8-3.el7.x86_64 docker-ce-cli-3:20.10.8-3.el7.x86_64 containerd.io

30.gif

  • 启动 Docker:
  1. # 启动 Docker
  2. systemctl start docker
  1. # 开启自动启动
  2. systemctl enable docker

31.gif

  • 验证 Docker 是否安装成功:
  1. docker version

32.gif

  • 阿里云镜像加速:
  1. sudo mkdir -p /etc/docker
  1. sudo tee /etc/docker/daemon.json <<-'EOF'
  2. {
  3. "exec-opts": ["native.cgroupdriver=systemd"],
  4. "registry-mirrors": [
  5. "https://du3ia00u.mirror.aliyuncs.com",
  6. "https://hub-mirror.c.163.com",
  7. "https://mirror.baidubce.com"
  8. ],
  9. "live-restore": true,
  10. "log-driver":"json-file",
  11. "log-opts": {"max-size":"500m", "max-file":"3"},
  12. "max-concurrent-downloads": 10,
  13. "max-concurrent-uploads": 5,
  14. "storage-driver": "overlay2"
  15. }
  16. EOF
  1. sudo systemctl daemon-reload
  1. sudo systemctl restart docker

33.gif

2.3.11 添加阿里云的 Kubernetes 的 YUM 源

  • 由于 Kubernetes 的镜像源在国外,非常慢,这里切换成国内的阿里云镜像源(三台机器均需执行下面命令):
  1. cat > /etc/yum.repos.d/kubernetes.repo << EOF
  2. [kubernetes]
  3. name=Kubernetes
  4. baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
  5. enabled=1
  6. gpgcheck=0
  7. repo_gpgcheck=0
  8. gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
  9. EOF

34.gif

2.3.12 安装 kubelet 、kubeadm 和 kubectl

  • 《1.4 搭建流程》中已经解释过,这里不再解释:
  1. yum install -y kubelet-1.21.10 kubeadm-1.21.10 kubectl-1.21.10

35.gif

  • 为了实现 Docker 使用的 cgroup drvier 和 kubelet 使用的 cgroup drver 一致,建议修改 /etc/sysconfig/kubelet 文件的内容:
  1. vim /etc/sysconfig/kubelet
  1. # 修改
  2. KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
  3. KUBE_PROXY_MODE="ipvs"

36.gif

  • 设置为开机自启动即可,由于没有生成配置文件,集群初始化后自动启动:
  1. systemctl enable kubelet

37.gif

2.4 查看 Kubernetes 安装所需镜像

  • 查看 Kubernetes 安装所需镜像:
  1. kubeadm config images list

38.gif

2.5 下载 Kubernetes 安装所需镜像

  • 三台机器下载镜像:
  1. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.21.10
  2. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.21.10
  3. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.21.10
  4. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.21.10
  5. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.4.1
  6. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0
  7. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0

39.gif

  • 给 coredns 镜像重新打 tag :
  1. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0 registry.cn-hangzhou.aliyuncs.com/google_containers/coredns/coredns:v1.8.0

40.gif

2.6 部署 Kubernetes 的 Master 节点

  • 在 192.168.65.100 机器上部署 Kubernetes 的 Master 节点:
  1. # 由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里需要指定阿里云镜像仓库地址
  2. kubeadm init \
  3. --apiserver-advertise-address=192.168.65.100 \
  4. --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers \
  5. --kubernetes-version=v1.21.10 \
  6. --service-cidr=10.96.0.0/16 \
  7. --pod-network-cidr=10.244.0.0/16

注意:

  • apiserver-advertise-address 一定要是主机的 IP 地址。
  • apiserver-advertise-address 、service-cidr 和 pod-network-cidr 不能在同一个网络范围内。
  • 不要使用 172.17.0.1/16 网段范围,因为这是 Docker 默认使用的。

41.gif

  • 日志:
  1. Your Kubernetes control-plane has initialized successfully!
  2. To start using your cluster, you need to run the following as a regular user:
  3. mkdir -p $HOME/.kube
  4. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  5. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  6. Alternatively, if you are the root user, you can run:
  7. export KUBECONFIG=/etc/kubernetes/admin.conf
  8. You should now deploy a pod network to the cluster.
  9. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  10. https://kubernetes.io/docs/concepts/cluster-administration/addons/
  11. Then you can join any number of worker nodes by running the following on each as root:
  12. kubeadm join 192.168.65.100:6443 --token tluojk.1n43p0wemwehcmmh \
  13. --discovery-token-ca-cert-hash sha256:c50b25a5e00e1a06cef46fa5d885265598b51303f1154f4b582e0df21abfa7cb
  • 根据日志提示操作,在 192.168.65.100 执行如下命令:
  1. mkdir -p $HOME/.kube
  2. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  3. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  1. # 如果是 root 用户,还可以执行如下命令
  2. export KUBECONFIG=/etc/kubernetes/admin.conf

42.gif

  • 默认的 token 有效期为 2 小时,当过期之后,该 token 就不能用了,这时可以使用如下的命令创建 token :
  1. kubeadm token create --print-join-command
  1. # 生成一个永不过期的token
  2. kubeadm token create --ttl 0 --print-join-command

2.7 部署 Kubernetes 的 Node节点

  • 根据日志提示操作,在 192.168.65.101 和 192.168.65.102 执行如下命令:
  1. kubeadm join 192.168.65.100:6443 --token tluojk.1n43p0wemwehcmmh \
  2. --discovery-token-ca-cert-hash sha256:c50b25a5e00e1a06cef46fa5d885265598b51303f1154f4b582e0df21abfa7cb

43.gif

2.8 部署网络插件

  • 官网

  • Kubernetes 支持多种网络插件,比如 flannel、calico、canal 等,任选一种即可,本次选择 calico(在 192.168.65.100 节点上执行,网络不行,请点这里 calico.yaml)。

  • calico 和 k8s 的版本对应
  1. kubectl apply -f https://projectcalico.docs.tigera.io/v3.19/manifests/calico.yaml

44.gif

备注:为什么使用 3.19 , 原因在这里

  • 查看部署 CNI 网络插件进度:
  1. kubectl get pods -n kube-system
  1. watch kubectl get pods -n kube-system

45.gif

2.9 查看节点状态

  • 在 Master(192.168.65.100)节点上查看节点状态:
  1. kubectl get nodes

46.gif

2.10 设置 kube-proxy 的 ipvs 模式

  • 在 Master(192.168.65.100)节点设置 kube-proxy 的 ipvs 模式:
  1. kubectl edit cm kube-proxy -n kube-system
  1. apiVersion: v1
  2. data:
  3. config.conf: |-
  4. apiVersion: kubeproxy.config.k8s.io/v1alpha1
  5. bindAddress: 0.0.0.0
  6. bindAddressHardFail: false
  7. clientConnection:
  8. acceptContentTypes: ""
  9. burst: 0
  10. contentType: ""
  11. kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
  12. qps: 0
  13. clusterCIDR: 10.244.0.0/16
  14. configSyncPeriod: 0s
  15. conntrack:
  16. maxPerCore: null
  17. min: null
  18. tcpCloseWaitTimeout: null
  19. tcpEstablishedTimeout: null
  20. detectLocalMode: ""
  21. enableProfiling: false
  22. healthzBindAddress: ""
  23. hostnameOverride: ""
  24. iptables:
  25. masqueradeAll: false
  26. masqueradeBit: null
  27. minSyncPeriod: 0s
  28. syncPeriod: 0s
  29. ipvs:
  30. excludeCIDRs: null
  31. minSyncPeriod: 0s
  32. scheduler: ""
  33. strictARP: false
  34. syncPeriod: 0s
  35. tcpFinTimeout: 0s
  36. tcpTimeout: 0s
  37. udpTimeout: 0s
  38. kind: KubeProxyConfiguration
  39. metricsBindAddress: ""
  40. mode: ""
  41. nodePortAddresses: null
  42. minSyncPeriod: 0s
  43. syncPeriod: 0s
  44. ipvs:
  45. excludeCIDRs: null
  46. minSyncPeriod: 0s
  47. scheduler: ""
  48. strictARP: false
  49. syncPeriod: 0s
  50. tcpFinTimeout: 0s
  51. tcpTimeout: 0s
  52. udpTimeout: 0s
  53. kind: KubeProxyConfiguration
  54. metricsBindAddress: ""
  55. mode: "ipvs" # 修改此处
  56. ...

47.gif

  • 删除 kube-proxy ,让 Kubernetes 集群自动创建新的 kube-proxy :
  1. kubectl delete pod -l k8s-app=kube-proxy -n kube-system

48.gif

2.11 让 Node 节点也能使用 kubectl 命令

  • 默认情况下,只有 Master 节点才有 kubectl 命令,但是有些时候我们也希望在 Node 节点上执行 kubectl 命令:
  1. # 192.168.65.101 和 192.168.65.102
  2. mkdir -pv ~/.kube
  3. touch ~/.kube/config
  1. # 192.168.65.100
  2. scp /etc/kubernetes/admin.conf root@192.168.65.101:~/.kube/config
  1. # 192.168.65.100
  2. scp /etc/kubernetes/admin.conf root@192.168.65.102:~/.kube/config

49.gif

2.12 Kubernetes 安装 Nginx

  • 部署 Nginx :
  1. kubectl create deployment nginx --image=nginx:1.14-alpine

50.gif

  • 暴露端口:
  1. kubectl expose deployment nginx --port=80 --type=NodePort

51.gif

  • 查看服务状态:
  1. kubectl get pods,svc

52.gif

2.13 自动补全

  • 官网

  • 命令:

    1. # 安装
    2. yum -y install bash-completion
    1. # 自动补全
    2. echo 'source <(kubectl completion bash)' >>~/.bashrc
    3. kubectl completion bash >/etc/bash_completion.d/kubectl
    4. # 全局
    5. kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
    6. source /usr/share/bash-completion/bash_completion

    53.gif