Skip to main content

使用kubeadm部署Kubernetes 1.26

文章目录

[TOC]

kubeadm是Kubernetes官方提供的用于快速安部署Kubernetes集群的工具,伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验kubeadm可以学习到Kubernetes官方在集群配置上一些新的最佳实践

1.准备

1.1 系统配置

在安装之前,需要先做好如下准备。6台Ubuntu22.04主机如下和一台dns服务器(可选,不用dns就改host文件):

cat /var/cache/bind/kuku.org.zone

$TTL 1D
@ IN SOA ns1.kuku.org. admin.kuku.org. (
2023010313; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
@ IN NS ns1.kuku.org.

ns1.kuku.org. IN A 192.168.1.30

kubeapi IN A 192.168.1.31
k8s-master01 IN A 192.168.1.31
k8s-master02 IN A 192.168.1.32
k8s-master03 IN A 192.168.1.33
k8s-node01 IN A 192.168.1.34
k8s-node02 IN A 192.168.1.35
k8s-node03 IN A 192.168.1.36

在各个主机上完成下面的系统配置。

设置各自的主机名,并且设置统一dns(可选)

sed -i '/\[Resolve\]/a DNS=192.168.1.30' /etc/systemd/resolved.conf && netplan apply

如果各个主机启用了防火墙策略,需要开放Kubernetes各个组件所需要的端口,可以查看Ports and Protocols中的内容, 开放相关端口或者关闭主机的防火墙。

禁用swap:

vim /etc/fstab 
#注释swap的行
#生效
swapoff -a

swappiness参数调整,修改/etc/sysctl.d/99-kubernetes-cri.conf添加下面一行:

vm.swappiness=0

执行sysctl -p /etc/sysctl.d/99-kubernetes-cri.conf使修改生效。

caution

使用free -m确认swap已经关闭

s

而后编辑/etc/fstab配置文件,注释用于挂载Swap设备的所有行。另外,在Ubuntu 2004及之后版本的系统上,若要彻底禁用Swap,可以需要类似如下命令进一步完成。 systemctl --type swap 而后,将上面命令列出的每个设备,使用systemctl mask命令加以禁用。 systemctl mask SWAP_DEV

禁用SELINUX(红帽系):

setenforce 0
vi /etc/selinux/config
SELINUX=disabled

创建/etc/modules-load.d/containerd.conf配置文件:

cat << EOF > /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter

执行生效命令:

modprobe overlay
modprobe br_netfilter

创建/etc/sysctl.d/99-kubernetes-cri.conf配置文件:

cat << EOF > /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
user.max_user_namespaces=28633
EOF

执行以下命令使配置生效:

sysctl -p /etc/sysctl.d/99-kubernetes-cri.conf

1.2 配置服务器支持开启ipvs的前提条件

由于ipvs已经加入到了内核的主干,所以为kube-proxy开启ipvs的前提需要加载以下的内核模块:

info

把nf_conntrack 替换成 nf_conntrack_ipv4 如果是Linux kernel 4.19 之前内核

ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack

在各个服务器节点上执行以下脚本:

mkdir -p /etc/sysconfig/modules
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
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack

上面脚本创建了的/etc/sysconfig/modules/ipvs.modules文件,保证在节点重启后能自动加载所需模块。 使用lsmod | grep -e ip_vs -e nf_conntrack命令查看是否已经正确加载所需的内核模块。

接下来还需要确保各个节点上已经安装了ipset软件包,为了便于查看ipvs的代理规则,最好安装一下管理工具ipvsadm。

apt install -y ipset ipvsadm
caution

如果不满足以上前提条件,则即使kube-proxy的配置开启了ipvs模式,也会退回到iptables模式。

1.3 部署容器运行时Containerd

在各个服务器节点上安装容器运行时Containerd。运行下面的脚本

#!/bin/bash
#
#*********************************************************
#Author: Ez4cyka
#QQ: NULL
#Date: 2023-03-03
#FileName: install_containerd.sh
#URL: https://ez4cyka.com
#Description: 安装containerd和kubelet kubeadm kubectl
#Copyright: 2023 All rights reserved
#********************************************************

#下载containerd二进制包
[ -f containerd-1.6.19-linux-amd64.tar.gz ] || wget https://github.com/containerd/containerd/releases/download/v1.6.19/containerd-1.6.19-linux-amd64.tar.gz
#解压到/usr/local下
tar Cxzvf /usr/local containerd-1.6.19-linux-amd64.tar.gz
#默认的systemd配置文件安排一下
[ -f containerd.service ] || wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
mkdir -p /usr/local/lib/systemd/system
cp containerd.service /usr/local/lib/systemd/system
systemctl daemon-reload
systemctl enable --now containerd
#安装runc
[ -f runc.amd64 ] || wget https://github.com/opencontainers/runc/releases/download/v1.1.4/runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc
#安装cni
mkdir -p /opt/cni/bin
[ -f cni-plugins-linux-amd64-v1.2.0.tgz ] || wget https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz
#解压到/opt/cni/bin下
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.2.0.tgz
#生成containerd配置文件
mkdir /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml


apt-get update
apt-get install -y apt-transport-https ca-certificates curl

apt-get update
apt-get install -y apt-transport-https ca-certificates curl

#官方的需要配置翻墙
#curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
#echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list

#阿里镜像国内可用
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

apt-get update
apt-get install -y kubelet kubeadm kubectl
#控制版本不变
apt-mark hold kubelet kubeadm kubectl

根据文档Container runtimes 中的内容,对于使用systemd作为init system的Linux的发行版,使用systemd作为容器的cgroup driver可以确保服务器节点在资源紧张的情况更加稳定,因此这里配置各个节点上containerd的cgroup driver为systemd。

修改脚本里生成的配置文件/etc/containerd/config.toml

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

再修改/etc/containerd/config.toml中的

[plugins."io.containerd.grpc.v1.cri"]
...
# sandbox_image = "k8s.gcr.io/pause:3.6"
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"

crictl 命令默认连接到 unix:///var/run/dockershim.sock 如果要连接到其他runtimes,需要设置 endpoint:

可以通过命令行参数 --runtime-endpoint--image-endpoint 可以通过设置环境变量 CONTAINER_RUNTIME_ENDPOINTCONTAINER_RUNTIME_ENDPOINT 可以通过配置文件的endpoint设置 --config=/etc/crictl.yaml 当前配置为 /etc/crictl.yaml :

cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
#debug: true
debug: false
EOF

重启下containerd并且设为开机启动

systemctl restart containerd
systemctl enable containerd

使用crictl version 测试一下,确保可以打印出版本信息并且没有错误信息输出:

Version:  0.1.0
RuntimeName: containerd
RuntimeVersion: v1.6.19
RuntimeApiVersion: v1

2.使用kubeadm部署Kubernetes

2.1 安装kubeadm和kubelet

上面的脚本中已经安装好了kubeadm和kubelet

2.2 使用kubeadm init初始化集群

在各节点开机启动kubelet服务:

systemctl enable kubelet.service

使用kubeadm config print init-defaults --component-configs KubeletConfiguration可以打印集群初始化默认的使用的配置:

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
...

从默认的配置中可以看到,可以使用imageRepository定制在集群初始化时拉取k8s所需镜像的地址。基于默认配置定制出本次使用kubeadm初始化集群所需的配置文件kubeadm.yaml

apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.1.31
bindPort: 6443
nodeRegistration:
criSocket: unix:///run/containerd/containerd.sock
taints:
- effect: PreferNoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
controlPlaneEndpoint: "kubeapi.kuku.org:6443"
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.26.2
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
failSwapOn: false
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

这里定制了imageRepository为阿里云的registry,避免因gcr被墙,无法直接拉取镜像。criSocket设置了容器运行时为containerd。 同时设置kubelet的cgroupDriver为systemd,设置kube-proxy代理模式为ipvs

在开始初始化集群之前可以使用kubeadm config images pull --config kubeadm.yaml预先在各个服务器节点上拉取所k8s需要的容器镜像。

kubeadm config images pull --config kubeadm.yaml
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.26.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.26.0
...

接下来使用kubeadm初始化集群,选择k8s-master01.kuku.org作为Master Node,在k8s-master01.kuku.org上执行下面的命令:

kubeadm init --config kubeadm.yaml --upload-certs

[init] Using Kubernetes version: v1.26.2
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master01.kuku.org kubeapi.kuku.org kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.1.31]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-master01.kuku.org localhost] and IPs [192.168.1.31 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-master01.kuku.org localhost] and IPs [192.168.1.31 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 12.503782 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master01.kuku.org as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8s-master01.kuku.org as control-plane by adding the taints [node-role.kubernetes.io/master:PreferNoSchedule]
[bootstrap-token] Using token: 221dxh.mzymxccje0yzdvu9
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[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

Alternatively, if you are the root user, you can run:

export KUBECONFIG=/etc/kubernetes/admin.conf

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/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

kubeadm join kubeapi.kuku.org:6443 --token 221dxh.mzymxccje0yzdvu9 \
--discovery-token-ca-cert-hash sha256:c913a00c0378fdf062eb3b524a70f03dcb8ae6e8295ab9e98a0451a7fd2ae1aa \
--control-plane

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join kubeapi.kuku.org:6443 --token 221dxh.mzymxccje0yzdvu9 \
--discovery-token-ca-cert-hash sha256:c913a00c0378fdf062eb3b524a70f03dcb8ae6e8295ab9e98a0451a7fd2ae1aa

上面记录了完成的初始化输出的内容,根据输出的内容基本上可以看出手动初始化安装一个Kubernetes集群所需要的关键步骤。 其中有以下关键内容:

  • [certs]生成相关的各种证书
  • [kubeconfig]生成相关的kubeconfig文件
  • [kubelet-start]生成kubelet的配置文件"/var/lib/kubelet/config.yaml"
  • [control-plane]使用/etc/kubernetes/manifests目录中的yaml文件创建apiserver、controller-manager、scheduler的静态pod
  • [bootstraptoken]生成token记录下来,后边使用kubeadm join往集群中添加节点时会用到
  • [addons]安装基本插件:CoreDNS, kube-proxy 下面的命令是配置常规用户如何使用kubectl访问集群:
  • 下面的命令是配置常规用户如何使用kubectl访问集群:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
  • 最后给出了将另外2个节点加入集群的命令:
  kubeadm join kubeapi.kuku.org:6443 --token 221dxh.mzymxccje0yzdvu9 \
--discovery-token-ca-cert-hash sha256:c913a00c0378fdf062eb3b524a70f03dcb8ae6e8295ab9e98a0451a7fd2ae1aa \
--control-plane

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join kubeapi.kuku.org:6443 --token 221dxh.mzymxccje0yzdvu9 \
--discovery-token-ca-cert-hash sha256:c913a00c0378fdf062eb3b524a70f03dcb8ae6e8295ab9e98a0451a7fd2ae1aa

看看集群状态和pods运行情况

kubectl get cs
kubectl get nodes
kubectl get pods -A -o wide

集群初始化如果遇到问题,可以使用kubeadm reset命令进行清理。

kubeadm reset
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
rm -rf /etc/cni/net.d
ipvsadm -C
rm -rf $HOME/.kube

2.3 安装包管理器helm 3

Helm是Kubernetes的包管理器,后续流程也将使用Helm安装Kubernetes的常用组件。 这里先在master01节点上安装helm。

wget https://get.helm.sh/helm-v3.10.3-linux-amd64.tar.gz
tar -zxvf helm-v3.10.3-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin/

执行helm list确认没有错误输出。

2.4部署Pod Network组件(flannel或者Calico)

2.4.1 选择flannel(轻量化,简单)

kubectl apply -f https://github.com/coreos/flannel/raw/master/Documentation/kube-flannel.yml

2.4.2 选择Calico (适合大规模,可扩展)