使用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
使修改生效。
使用free -m确认swap已经关闭
而后编辑/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的前提需要加载以下的内核模块:
把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
如果不满足以上前提条件,则即使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_ENDPOINT
和 CONTAINER_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