基础环境

关闭防火墙

关闭防火墙,selinux
systemctl stop firewalld && systemctl disable  firewalld

关闭elinux

setenforce 0
sed -i s/SELINUX=enforcing/SELINUX=disabled/ /etc/selinux/config

关闭swap分区

swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

问题:k8s集群安装为什么需要关闭swap分区?

swap必须关,否则kubelet起不来,进而导致k8s集群起不来;
可能kublet考虑到用swap做数据交换的话,对性能影响比较大;

配置dns解析

cat >> /etc/hosts << EOF
172.29.9.51 master1
172.29.9.52 node1
172.29.9.53 node2
EOF

问题:k8s集群安装时节点是否需要配置dns解析?

就是后面的kubectl如果需要连接运行在node上面的容器的话,它是通过kubectl get node出来的名称去连接的,所以那个的话,我们需要在宿主机上能够解析到它。如果它解析不到的话,那么他就可能连不上;

安装 ipvs

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  # 4.19内核将nf_conntrack_ipv4更名为nf_conntrack
EOF


chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack  

yum install ipset -y
yum install ipvsadm -y

说明:

  • 上面脚本创建了的/etc/sysconfig/modules/ipvs.modules文件,保证在节点重启后能自动加载所需模块。使用 lsmod | grep -e ip_vs -e nf_conntrack 命令查看是否已经正确加载所需的内核模块;
  • 要确保各个节点上已经安装了 ipset 软件包,因此需要:yum install ipset -y;
  • 为了便于查看 ipvs 的代理规则,最好安装一下管理工具 ipvsadm:yum install ipvsadm -y

ipset

ip set 是linux内核的一个内部框架, 可由ipset工具管理,ip set 可以分为以下几种类型:ip地址, 网路地址(网段),tcp/udp 端口号, mac地址, 网卡名称。或者是上述类型的组合,并保证快速的匹配。

ipset 适用于以下几种场景:
(1)一次性存储大量的ip或者端口,用以iptables匹配
(2)在不影响性能的前提下,动态更新iptables规则(针对ip或者端口)
(3)期望使用ipset的告诉匹配,或者在一条iptables规则中表达复杂的 ip/端口规则

同步服务器时间

yum install chrony -y
systemctl enable chronyd --now
chronyc sources

Containerd

配置内核参数

cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# Setup required sysctl params, these persist across reboots.
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# Apply sysctl params without reboot
sudo sysctl --system

安装

卸载之前的版本

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

安装 yum-utils

sudo yum install -y yum-utils

安装 containerd

yum install containerd.io

配置

如果 /etc/containerd/ 中没有配置文件,需要创建

mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

将 containerd 的 cgroup driver 配置为 systemd

对于使用 systemd 作为 init system 的 Linux 的发行版,使用 systemd 作为容器的 cgroup driver 可以确保节点在资源紧张的情况更加稳定,所以推荐将 containerd 的 cgroup driver 配置为 systemd。

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

配置 sandbox_image

特别注意:containerd 中 sandbox_image pause 镜像版本会覆盖 pause 镜像版本
/etc/containerd/config.toml

sandbox_image = "k8s.gcr.io/pause:3.2" ==> 3.6 # 设置成 kubeadm 需要的 pause 镜像版本

配置代理

无法下载 k8s.gcr.io 中的精选,需要设置代理。containerd 不像 docker 那样支持使用 systemd 方式配置代理。但是可以通过配置全局代理,让 containerd 可以通过代理下载镜像。

vim ~/.bashrc

export HTTP_PROXY="http://<user>:<password>@<proxy_server>:<port>"
export HTTPS_PROXY="http://<user>:<password>@<proxy_server>:<port>"

然后应用配置

source ~/.bashrc

启动

systemctl daemon-reload
systemctl enable --now containerd.service

验证

$ ctr version
Client:
  Version:  1.4.12
  Revision: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
  Go version: go1.16.10

Server:
  Version:  1.4.12
  Revision: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
  UUID: d1df458b-b13c-4a65-9579-4c914abf0e00

$ rictl version
Version:  0.1.0
RuntimeName:  containerd
RuntimeVersion:  1.4.12
RuntimeApiVersion:  v1alpha2

kubeadm

配置内核参数

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system

注意:将桥接的IPv4流量传递到iptables的链
由于开启内核 ipv4 转发需要加载 br_netfilter 模块,所以加载下该模块:
modprobe br_netfilter

bridge-nf 使得 netfilter 可以对 Linux 网桥上的 IPv4/ARP/IPv6 包过滤。比如,设置net.bridge.bridge-nf-call-iptables=1后,二层的网桥在转发包时也会被 iptables的 FORWARD 规则所过滤。常用的选项包括:

  • net.bridge.bridge-nf-call-arptables:是否在 arptables 的 FORWARD 中过滤网桥的 ARP 包
  • net.bridge.bridge-nf-call-ip6tables:是否在 ip6tables 链中过滤 IPv6 包
  • net.bridge.bridge-nf-call-iptables:是否在 iptables 链中过滤 IPv4 包
  • net.bridge.bridge-nf-filter-vlan-tagged:是否在 iptables/arptables 中过滤打了 vlan 标签的包。

配置 yum 源

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.cloud.tencent.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
repo_gpgcheck=0
exclude=kubelet kubeadm kubectl
EOF

关闭 SELinux

# Set SELinux in permissive mode (effectively disabling it)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

安装

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet

说明:--disableexcludes 禁掉除了kubernetes之外的别的仓库

初始化集群

master节点配置

然后我们可以通过下面的命令在 master 节点上输出集群初始化默认使用的配置:

# 生成默认配置
kubeadm config print init-defaults --component-configs KubeletConfiguration > kubeadm.yaml

# 生成KubeletConfiguration示例文件
kubeadm config print init-defaults --component-configs KubeletConfiguration

# 生成KubeProxyConfiguration示例文件
kubeadm config print init-defaults --component-configs KubeProxyConfiguration

cat kubeadm.yaml

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 10.0.24.16 # master 节点的 IP
  bindPort: 6443
nodeRegistration:
  criSocket: /run/containerd/containerd.sock  # 修改成 containerd.sock 
  imagePullPolicy: IfNotPresent
  name: master  修改成 master 节点 hostname
  taints: null
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  external:  # 配置外部 etcd 集群
    endpoints:
    - https://172.21.16.14:2379
    - https://172.21.16.6:2379
    - https://172.21.16.13:2379
    caFile: /root/kubeadm-init/ssl/ca.pem
    certFile: /root/kubeadm-init/ssl/client.pem
    keyFile: /root/kubeadm-init/ssl/client-key.pem
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: 1.22.4   # 修改 kubernetes 集群版本
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/16  # 修改 service IP 段
  podSubnet: 10.97.0.0/16      # 修改 pod IP 段
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 0s
    cacheUnauthorizedTTL: 0s
cgroupDriver: systemd   # 配置 cgroup driver
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
cpuManagerReconcilePeriod: 0s
evictionPressureTransitionPeriod: 0s
fileCheckFrequency: 0s
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 0s
imageMinimumGCAge: 0s
kind: KubeletConfiguration
logging: {}
memorySwap: {}
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
rotateCertificates: true
runtimeRequestTimeout: 0s
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"

网络配置

kubeadm配置文件中podSubnet 和 flannel 配置文件中 Network 需要一致

kubeadm.yaml

podSubnet: 10.97.0.0/16 

flannel.yaml

net-conf.json: |
    {
      "Network": "10.97.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }

然后根据我们自己的需求修改配置,比如修改 imageRepository 指定集群初始化时拉取 Kubernetes 所需镜像的地址,kube-proxy 的模式为 ipvs,另外需要注意的是我们这里是准备安装 flannel 网络插件的,需要将 networking.podSubnet 设置为10.244.0.0/16:

拉取 k8s 容器镜像

查看镜像

kubeadm config images list
I1211 19:12:18.444683  199744 version.go:255] remote version is much newer: v1.23.0; falling back to: stable-1.22
k8s.gcr.io/kube-apiserver:v1.22.4
k8s.gcr.io/kube-controller-manager:v1.22.4
k8s.gcr.io/kube-scheduler:v1.22.4
k8s.gcr.io/kube-proxy:v1.22.4
k8s.gcr.io/pause:3.5
k8s.gcr.io/etcd:3.5.0-0
k8s.gcr.io/coredns/coredns:v1.8.4

kubeadm config images list --config kubeadm.yaml
k8s.gcr.io/kube-apiserver:v1.22.4
k8s.gcr.io/kube-controller-manager:v1.22.4
k8s.gcr.io/kube-scheduler:v1.22.4
k8s.gcr.io/kube-proxy:v1.22.4
k8s.gcr.io/pause:3.5
k8s.gcr.io/coredns/coredns:v1.8.4

下载镜像

配置文件准备好过后,可以使用如下命令先将相关镜像 pull 下面:

kubeadm config images pull --config kubeadm.yaml

worker 节点配置

# 加入集群
kubeadm join 192.168.31.139:6443 --token --discovery-token-ca-cert-hash XXX sha256:XXX

# 生成用于添加节点的kubeadm-config.yaml文件
kubeadm config print join-defaults > kubeadm-config.yaml
# 添加节点:
kubeadm join --config kubeadm-config.yaml

网络配置

flannel 安装

# For Kubernetes v1.17+ 
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

修改网络配置:kube-flannel.yml

net-conf.json: |
    {
      "Network": "10.97.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }

安装配置

kubectl apply -f kube-flannel.yml

nfs 插件安装

安装 helm

# 下载
https://github.com/helm/helm/releases

# 解压
tar -zxvf helm-v3.0.0-linux-amd64.tar.gz

# 添加执行权限
chmod +x helm

# 在解压目中找到helm程序,移动到需要的目录中
mv helm /usr/local/bin/

安装 nfs

github 地址
https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

$ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

$ helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=x.x.x.x \
    --set nfs.path=/exported/path

所需要的镜像
k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2