第八周作业

部署

架构信息

网络类型 网段信息
节点网络 192.168.100.0/24
service网络 10.96.0.0/12
pod网络 10.244.0.0/16
工具 版本 用途
kubeadm 1.29.2 Kubernetes集群管理
docker 25.0.3 容器化平台
cri-dockerd 0.3.10 容器运行时接口
kubernetes 1.29.2 容器编排系统
flannel v0.25.3 网络插件
flannel-cni-plugin v1.4.1-flannel1 CNI网络插件
ipvs 1.31 流量路由与服务代理
节点 操作系统 主机名 角色
192.168.100.110/24 Ubuntu 22.04 LTS k8s-master01.alfie.com
kubeapi.alfie.com
Master
192.168.100.121/24 Ubuntu 22.04 LTS k8s-node01.alfie.com Worker
192.168.100.122/24 Ubuntu 22.04 LTS k8s-node02.alfie.com Worker
192.168.100.123/24 Ubuntu 22.04 LTS k8s-node03.alfie.com Worker

标识信息更新

# 确认唯一UUID
cat /sys/class/dmi/id/product_uuid

# 初始化变量定义
api=k8s-api.alfie.com
m1=k8s-master01.alfie.com
w1=k8s-node01.alfie.com
w2=k8s-node02.alfie.com
w3=k8s-node03.alfie.com

m1_ip=192.168.100.110
w1_ip=192.168.100.121
w2_ip=192.168.100.122
w3_ip=192.168.100.123

# hostname 修改
hostnamectl set-hostname ${hn}

# hosts记录更新
cat > /etc/hosts <<EOF
${m1_ip} ${api}
${m1_ip} ${m1}
${w1_ip} ${w1}
${w2_ip} ${w2}
${w3_ip} ${w3}
EOF

# 按主机修改ip
ip=${xxx}
hn=${yyy}

# Ubuntu系列修改IP
sed -i.bak "6c\        - ${ip}/24" \
/etc/netplan/00-installer-config.yaml
netplan apply

使用国内源

bash -c "cat < EOF > /etc/apt/sources.list && apt update
deb http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
EOF"

时间同步

# 修改时区为中国时间
timedatectl set-timezone Asia/Shanghai

# 关闭此前的默认时间同步工具
systemctl unmask systemd-timesyncd.service
systemctl disable --now systemd-timesyncd.service

apt -y install chrony
mv /etc/chrony/chrony.conf /etc/chrony/chrony.conf.bak

cat > /etc/chrony/chrony.conf << EOF
server ntp1.aliyun.com iburst minpoll 4 maxpoll 10
server ntp2.aliyun.com iburst minpoll 4 maxpoll 10
server ntp3.aliyun.com iburst minpoll 4 maxpoll 10
server ntp4.aliyun.com iburst minpoll 4 maxpoll 10
server ntp5.aliyun.com iburst minpoll 4 maxpoll 10
server ntp6.aliyun.com iburst minpoll 4 maxpoll 10
server ntp7.aliyun.com iburst minpoll 4 maxpoll 10
driftfile /var/lib/chrony/drift
makestep 10 3
rtcsync
allow 0.0.0.0/0
local stratum 10
#keyfile /etc/chrony.keys
logdir /var/log/chrony
stratumweight 0.05
noclientlog
logchange 0.5
EOF

# 开启当前时间同步chrony
systemctl daemon-reload
systemctl enable --now chrony.service

关闭swap

sed -ri.bak 's/.*swap.*/#&/' /etc/fstab
swappoff -a
#sed -n '/swap/ s/\(.*\)/# \1/gp' /etc/fstab
systemctl disable --now swap.target 

# 检查是否关闭
swapon --show

关闭防火墙


ref

ufw disable
ufw status

内核优化

cat > /etc/sysctl.d/k8s.conf <<EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.netfilter.nf_conntrack_max=2310720
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl =15
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 65536
net.ipv4.tcp_max_syn_backlog = 16384
net.core.somaxconn = 16384
EOF

# 重新加载配置
sysctl --system

# 文件资源限制
sudo sh -c 'cat >> /etc/security/limits.d/k8s.conf <<EOF
* soft nofile 65535
* hard nofile 131070
EOF'

ulimit -Sn 
ulimit -Hn

必备软件

apt -y install tree nmap sysstat \
lrzsz dos2unix telnet vim lsof net-tools \
rsync wget jq psmisc ipvsadm \
lvm2 git curl tar bash-completion expect \
apt-transport-https ca-certificates curl ipset iputils-ping

运行时选择

docker + cri-dockered

docker

# 安装docker
#0. 卸载此前的docker
sudo apt purge docker-ce \
docker-ce-cli  \
docker-buildx-plugin \
docker-ce-rootless-extras \
docker-compose-plugin \
containerd.io \
docker-scan-plugin && sudo rm -rf /var/lib/docker && sudo apt autoremove

#1. 安装必备工具
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common

#2. 安装GPG证书
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

#3. 写入仓库
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

#4. 查询版本
apt-cache madison docker-ce
>  docker-ce | 5:25.0.3-1~ubuntu.22.04~jammy | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages

#5. 安装指定docker-ce (指定版本不能只指定docker-ce,否则其他都会使用最新版本造成不是适配)
v='5:25.0.3-1~ubuntu.22.04~jammy'
sudo apt-get install docker-ce=$v \
docker-ce-cli=$v \
docker-ce-rootless-extras=$v 

#6. 配置镜像加速
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": [
    "https://registry.cn-hangzhou.aliyuncs.com"
  ],
  "exec-opts": [
    "native.cgroupdriver=systemd"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "200m"
  },
  "storage-driver": "overlay2"
}
EOF

#7. 配置代理
vim /lib/systemd/system/docker.service
[Service]
Environment="HTTP_PROXY=http://$PROXY_SERVER_IP:$PROXY_PORT"
Environment="HTTPS_PROXY=http://$PROXY_SERVER_IP:$PROXY_PORT"
Environment="NO_PROXY=127.0.0.0/8,192.168.100.0/24,10.244.0.0/16,192.168.0.0/16,10.96.0.0/12,alfie.com,cluster.local"

#8. 配置加载
systemctl daemon-reload && systemctl start docker

#9. 查看版本
docker version

cir-dockered

Docker Engine默认不支持CRI规范,Kubernetes自v1.24移除了对docker-shim的支持。
cri-dockerd可以为Docker Engine提供一个能够支持到CRI规范的垫片,从而能够让Kubernetes基于CRI控制Docker。

源地址:https://github.com/Mirantis/cri-dockerd

# 下载安装包
curl -LO https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.10/cri-dockerd_0.3.10.3-0.ubuntu-jammy_amd64.deb

# 安装
dpkg -i ./cri-dockerd_0.3.10.3-0.ubuntu-jammy_amd64.deb
#apt install ./cri-dockerd_0.3.10.3-0.ubuntu-jammy_amd64.deb

# 查看其状态
systemctl status cri-docker.service

整合运行时

!!! warning 警告

cri-dockerd模式需执行.
!!!

vim /usr/lib/systemd/system/cri-docker.service

ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --cni-bin-dir=/opt/cni/bin --cni-cache-dir=/var/lib/cni/cache --cni-conf-dir=/etc/cni/net.d --pod-infra-container-image=registry.k8s.io/pause:3.9

    --network-plugin:指定网络插件规范的类型,这里要使用CNI;
    --cni-bin-dir:指定CNI插件二进制程序文件的搜索目录; 
    --cni-cache-dir:CNI插件使用的缓存目录; 
    --cni-conf-dir:CNI插件加载配置文件的目录; 
    --pod-infra-container-image:Pod中的puase容器要使用的Image,默认为registry.k8s.io上的pause仓库中的镜像;不能直接获取到该Image时,需要明确指定为从指定的位置加载,例如“registry.aliyuncs.com/google_containers/pause:3.9”。

# 重启服务
systemctl daemon-reload && systemctl restart cri-docker.service

Containerd

# 导入containerd密钥
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add -

# 添加库
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

# 更新库
apt update

# 安装
apt-get  install  containerd.io

# 配置
## 生成默认配置
mkdir /etc/containerd
containerd config default > /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

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

[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
    endpoint = ["https://docker.mirrors.ustc.edu.cn", "https://registry.docker-cn.com"]

[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
endpoint = ["https://registry.aliyuncs.com/google_containers"]

[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.magedu.com"]
    endpoint = ["https://registry.magedu.com"]

systemctl daemon-reload  && systemctl restart containerd

vim /etc/crictl.yam
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: true

kube*安装

# 导入gpg证书
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 写入源文件
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 查看当前支持版本
apt-cache madison kublet 
>   kubelet | 1.29.2-1.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages

# 安装 kublet, kubeadm, kubectl
v=1.29.2-1.1
apt-get update
apt-get install -y kubelet=$v kubeadm=$v kubectl=$v
apt-mark hold kubelet kubeadm kubectl

Master初始化

镜像获得

# 只能获得最新大版本下的镜像
kubeadm config images list

# 指定所需的版本镜像
kubeadm config images list --kubernetes-version v1.29.2
> registry.k8s.io/kube-apiserver:v1.29.2
> registry.k8s.io/kube-controller-manager:v1.29.2
> registry.k8s.io/kube-scheduler:v1.29.2
> registry.k8s.io/kube-proxy:v1.29.2
> registry.k8s.io/coredns/coredns:v1.11.1
> registry.k8s.io/pause:3.9
> registry.k8s.io/etcd:3.5.10-0

# 二选一
  # 查看国内源list
    kubeadm config images list --image-repository=registry.aliyuncs.com/google_containers --kubernetes-version v1.29.2
    ## 通过国内源下载
    kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers --kubernetes-version v1.29.2
    ## 修改镜像tag
    docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.29.2  registry.k8s.io/kube-apiserver:v1.29.2
    ...

    ## 通过国外源下载
    ## 使用cri-dockerd 需要添加 --cri-socket
    kubeadm config images pull --kubernetes-version v1.29.2 --cri-socket=unix:///var/run/cri-dockerd.sock
    
    ## 使用contained则使用如下命令
    kubeadm config images pull --kubernetes-version v1.29.2

初始化选择

命令行初始化

kubeadm init \
      --control-plane-endpoint="k8s-master01.alfie.com" \
      --kubernetes-version=v1.29.2 \
      --pod-network-cidr=10.244.0.0/16 \
      --service-cidr=10.96.0.0/12 \
      --token-ttl=0 \
      --upload-certs \
      --cri-socket=unix:///var/run/cri-dockerd.sock

!!! warning 说明

对于使用 docker + cri-dockered容器运行时,需要添加--cri-socket 配置。
!!!

!!! tip 参数说明

  • --image-repository:指定要使用的镜像仓库,默认为registry.k8s.io;

  • --kubernetes-version:kubernetes程序组件的版本号,它必须要与安装的kubelet程序包的版本号相同;

  • --control-plane-endpoint:控制平面的固定访问端点,可以是IP地址DNS名称,会被用于集群管理员及集群组件的kubeconfig配置文件的API Server的访问地址;单控制平面部署时可以不使用该选项

  • --pod-network-cidr:Pod网络的地址范围,其值为CIDR格式的网络地址。

    • Flannel网络插件的默认为10.244.0.0/16
    • Project Calico插件的默认值为192.168.0.0/16
    • Cilium的默认值为10.0.0.0/8
  • --service-cidr:Service的网络地址范围,其值为CIDR格式的网络地址

    • kubeadm使用的默认为10.96.0.0/12;通常,仅在使用Flannel一类的网络插件需要手动指定该地址;
  • --apiserver-advertise-address:apiserver通告给其他组件的IP地址,一般应该为Master节点的用于集群内部通信的IP地址,0.0.0.0表示节点上所有可用地址;

  • --upload-certs:将控制平面证书上传到 kubeadm-certs Secret。

  • mode

  • --token-ttl:共享令牌(token)的过期时长,默认为24小时0表示永不过期;为防止不安全存储等原因导致的令牌泄露危及集群安全,建议为其设定过期时长。未设定该选项时,在token过期后,若期望再向集群中加入其它节点,可以使用如下命令重新创建token,并生成节点加入命令。
    !!!

文件初始化

kubeadm config print init-defaults

!!! warning 文件初始化

文件初始化最主要是可以实现更多精细化控制,例如此处使用ipvsmode,默认使用iptables
!!!

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
  - groups:
      - system:bootstrappers:kubeadm:default-node-token
    token: alfie.comc4mu9kzd5q7ur
    ttl: 24h0m0s
    usages:
      - signing
      - authentication
kind: InitConfiguration
localAPIEndpoint:
  # 这里的地址即为初始化的控制平面第一个节点的IP地址;
  advertiseAddress: 192.168.100.110
  bindPort: 6443
nodeRegistration:
  # 注意,使用docker-ce和cri-dockerd时,要启用如下配置的cri socket文件的路径;
  criSocket: unix:///run/cri-dockerd.sock
  imagePullPolicy: IfNotPresent
  # 第一个控制平面节点的主机名称;
  name: k8s-master01.magedu.com
  taints:
    - effect: NoSchedule
      key: node-role.kubernetes.io/master
    - effect: NoSchedule
      key: node-role.kubernetes.io/control-plane
---
apiServer:
  timeoutForControlPlane: 4m0s
  # 将下面配置中的certSANS列表中的值,修改为客户端接入API Server时可能会使用的各类目标地址;
  certSANs:
    - kubeapi.alfie.com
    - 192.168.100.110
apiVersion: kubeadm.k8s.io/v1beta3
# 控制平面的接入端点,我们这里选择适配到kubeapi.alfie.com这一域名上;
controlPlaneEndpoint: "kubeapi.alfie.com:6443"
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.29.2
networking:
  # 集群要使用的域名,默认为cluster.local
  dnsDomain: cluster.local
  # service网络的地址
  serviceSubnet: 10.96.0.0/12
  # pod网络的地址,flannel网络插件默认使用10.244.0.0/16
  podSubnet: 10.244.0.0/16
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
# 用于配置kube-proxy上为Service指定的代理模式,默认为iptables;
mode: "ipvs"

凭据复制

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

网络插件部署

# 部署flannel
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

# 验证cri容器安装
kubectl get pods -n kube-flannel

增添Master

# 使用`docker+cri-dockered`作为运行时,需要使用 `--cri-socket`指定运行时
  kubeadm join k8s-master01.alfie.com:6443 --token n2fewy.h1fwv3svdrf9l6w8 \
    --discovery-token-ca-cert-hash sha256:d0b3fb23632bb02fddad5789e1cb09c34161a152421bf23e3263bce54800392f \
    --control-plane --certificate-key 927190558e3213e44841da9aa5de38391882db7a47bc83244df49a0f6f904d0b
    --cri-socket=unix:///var/run/cri-dockerd.sock

Worker加入

# 使用`docker+cri-dockered`作为运行时,需要使用 `--cri-socket`指定运行时
kubeadm join k8s-master01.alfie.com:6443 --token n2fewy.h1fwv3svdrf9l6w8 \
    --discovery-token-ca-cert-hash sha256:d0b3fb23632bb02fddad5789e1cb09c34161a152421bf23e3263bce54800392f \
    --cri-socket=unix:///var/run/cri-dockerd.sock

!!! warning 说明

对于使用 docker + cri-dockered容器运行时,需要添加--cri-socket 配置。
!!!

验证

# 查看集群节点
kubectl get nodes

升级

!!! success 步骤

  1. 先升级控制平面节点
  2. 后再升级工作节点

排空节点,而后升级kubelet和kubectl
official doc
!!!

重置

kubeadm reset

尽最大努力还原通过 kubeadm init 或者 kubeadm join 命令对主机所作的更改, 一般需要配置--cri-socket选项使用。

该操作往往在需要重置整个集群时使用,同时需要删除相关文件、清理iptables/ipvs规则。

证书管理

kubeadm为各节点默认生成的SSL证书的有效期限为1年,在到期之前需要renew这些证书

证书检查

kubeadm certs check-expiration

更新证书

kubeadm certs renew
kubeadm会在控制平面升级自动更新所有的证书

kube-proxy 工作模式切换

1. 配置configmap
kubectl edit configmap kube-proxy -n kube-system

2. 修改mode
    mode: "ipvs"
3. 删除所有kube-proxy pods
    kubectl get po -n kube-system
    kubectl delete po -n kube-system <pod-name>
4. 验证kube-proxy pod 是否采用了 ipvs
    kubectl logs [kube-proxy pod] -n kube-system| grep "Using ipvs Proxier"


问题处理

Found multiple CRI endpoints on the host

  • 原因:当前使用的容器运行时,选择docker + cri-dockered,在通过pull获取镜像时被检测到多个CRI环境
  • 解决方式:通过追加--cri-socket=unix:///var/run/cri-dockerd.sock 即可解决

指定kubeadm拉取镜像的版本

  • 问题:kubeadm默认会拉起该子版本最新的镜像,这不一定是我们需要的
    • 例如当前为1.29.2 版本,它会拖取当前最新的最新的1.29.5
  • 解决方式:通过追加--kubernetes-version vX.YY.Z可以解决我们指定版本的需求
  • ref