跳到主要内容

Centos8 ARM64

2024年08月19日
柏拉文
越努力,越幸运

一、认识


在本文中,我们将详细介绍如何在 Apple M1 Mac 上使用 VMFunction 虚拟机安装 CentOS 8 ARM64 系统,并在此基础上搭建一个 Kubernetes 集群,采用 containerd 作为容器运行时。随着 ARM64 架构在现代计算中的普及,特别是 Apple M1 芯片的广泛应用,了解如何在 ARM64 平台上部署和管理 Kubernetes 集群变得尤为重要。本文将涵盖从在 M1 Mac 上设置虚拟机、安装 CentOS 8 ARM64,到配置 Kubernetes 集群和使用 containerd 运行时的完整过程,帮助您在 ARM64 环境中高效地运行 Kubernetes

二、初始化前准备


2.1 配置主机名

配置主机名对集群管理至关重要。Kubernetes 集群中的节点需要通过主机名来识别和通信。

hostnamectl set-hostname k8s-master
hostnamectl set-hostname k8s-node1
hostnamectl set-hostname k8s-node2

2.2 配置时间同步

时间同步确保集群中的所有节点时间一致,避免时间偏差影响集群操作。使用 chrony 来同步时间。

1. 配置时间同步

yum install -y chrony
systemctl start chronyd
systemctl enable chronyd

2. 验证时间同步

sleep 4
chronyc sources

2.3 配置 Hosts

将集群节点的 IP 地址和主机名添加到 /etc/hosts 文件中,确保节点能够通过主机名互相识别。

K8S_HOST_ENTRIES=(
"192.168.105.132 k8s-master"
"192.168.105.133 k8s-node1"
"192.168.105.134 k8s-node2"
)

update_hosts() {
for entry in "${K8S_HOST_ENTRIES[@]}"; do
if ! grep -q "$entry" /etc/hosts; then
echo "$entry" >> /etc/hosts || handle_error "Failed to update /etc/hosts with $entry"
echo "/etc/hosts updated with $entry"
else
echo "/etc/hosts already contains $entry"
fi
done
}

2.4 关闭 Swap

Kuberneteskubelet 组件依赖系统内存调度策略,关闭 Swap 可以防止内存分配不确定性,确保 kubelet 的稳定性。

1. 关闭 Swap

swapoff -a  # 临时
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab # 永久

2. 验证 Swap 是否关闭

free

2.5 关闭防火墙

为了确保 Kubernetes 组件之间的自由通信,需关闭防火墙。

1. 关闭防火墙

systemctl stop firewalld
systemctl disable firewalld

2, 检测防火墙状态

systemctl status firewalld

2.6 关闭 Selinux

SELinux 的安全策略可能会阻止 Kubernetes 的操作。关闭 SELinux 以确保服务能够正常启动。

1. 关闭 Selinux

setenforce 0  # 临时
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config # 永久

2. 验证 SeLinux 是否关闭

getenforce // 结果为 Permissive, 则表示 setenforce 已成功关闭 SELinux。

2.7 配置 Iptables

正确配置 Iptables 是集群网络正常运行的关键,确保 Kubernetes 组件能够正确处理网络流量。

yum install ipset ipvsadm -y

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

sudo modprobe ip_vs
sudo modprobe overlay
sudo modprobe ip_vs_sh
sudo modprobe ip_vs_rr
sudo modprobe ip_vs_wrr
sudo modprobe br_netfilter
sudo modprobe nf_conntrack_ipv4

# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF

# 应用 sysctl 参数而不重新启动
sudo sysctl --system

# 通过运行以下指令确认 br_netfilter 和 overlay 模块被加载

lsmod | grep br_netfilter
lsmod | grep overlay

# 通过运行以下指令确认 net.bridge.bridge-nf-call-iptables、net.bridge.bridge-nf-call-ip6tables 和 net.ipv4.ip_forward 系统变量在你的 sysctl 配置中被设置为 1
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

2.8 配置 Docker Cgroup 驱动

通过 yum 的方式安装 docker-ce, 同时会安装 containerdrunccnicrictl。安装成功后,配置 Docker 驱动方式。KubernetesDocker 使用 cgroup 来管理资源,配置一致的 cgroup 驱动可以避免管理不一致性和潜在的资源竞争问题。更改 /etc/docker/daemon.json 配置如下:

# 配置加速器
DOCKER_MIRROR_URL="https://624m5g3q.mirror.aliyuncs.com"

cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["'$DOCKER_MIRROR_URL'", "https://registry.docker-cn.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

# 重启 Docker
systemctl restart docker

2.9 配置 Containerd 运行时

通过 yum 的方式安装 docker-ce, 同时会安装 containerdrunccnicrictlcontainerdKubernetes 推荐的容器运行时,它与 Kubernetes 集成良好并提供更轻量级的容器管理。配置 containerd 作为容器运行时,并设置镜像加速器,优化容器管理和镜像拉取速度。

1. 配置 containerd

sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml

#1. 添加 config_path = "/etc/containerd/certs.d"
sed -i 's/config_path\ =.*/config_path = \"\/etc\/containerd\/certs.d\"/g' /etc/containerd/config.toml
mkdir /etc/containerd/certs.d/docker.io -p
cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"
[host."https://624m5g3q.mirror.aliyuncs.com"]
capabilities = ["pull", "resolve"]
EOF

#2. 把SystemdCgroup = false修改为:SystemdCgroup = true
sed -i 's/SystemdCgroup\ =\ false/SystemdCgroup\ =\ true/g' /etc/containerd/config.toml

#3. 把sandbox_image = "k8s.gcr.io/pause:3.6"修改为:sandbox_image="registry.aliyuncs.com/google_containers/pause:3.9"
sed -i 's/sandbox_image\ =.*/sandbox_image\ =\ "registry.aliyuncs.com\/google_containers\/pause:3.8"/g' /etc/containerd/config.toml|grep sandbox_image

2. 启动 containerd

systemctl daemon-reload 
systemctl enable containerd
systemctl restart containerd

3. 验证 containerd

sudo systemctl status containerd

2.10 配置 CriCtl 容器管理

通过 yum 的方式安装 docker-ce, 同时会安装 containerdrunccnicrictl。配置 crictl 作为 CRI 兼容的容器运行时命令行工具,用于检查和调试 Kubernetes 节点上的容器运行时。

1. 配置 CriCtl 容器管理

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
EOF

2. 重启 containerd

systemctl restart containerd

3. 验证 CriCtl

crictl --version

2.11 将以上操作步骤沉淀为脚本

1. 沉淀脚本,并命名为 prepare_kubernetes.sh

#!/bin/bash

set -e # 遇到错误时停止脚本执行

# 主机 IP 和名称配置
declare -A K8S_HOST_ENTRIES=(
["192.168.105.132"]="k8s-master"
["192.168.105.133"]="k8s-node1"
["192.168.105.134"]="k8s-node2"
)

CONTAINERD_CONFIG_FILE="/etc/containerd/config.toml"
DOCKER_MIRROR_URL="https://624m5g3q.mirror.aliyuncs.com"

handle_error() {
echo "Error: $1"
exit 1
}

check_root() {
if [ "$(id -u)" -ne 0 ]; then
handle_error "This script must be run as root. Please run as root or with sudo."
fi
}

set_hostname() {
echo "============"
echo "开始配置主机名"
echo "============"

local HOSTNAME=$1
if [ "$(hostnamectl --static)" != "$HOSTNAME" ]; then
hostnamectl set-hostname "$HOSTNAME" || handle_error "Failed to set hostname to $HOSTNAME"
echo "Hostname set to $HOSTNAME"
else
echo "Hostname is already set to $HOSTNAME"
fi

echo "============"
echo "主机名配置成功!"
echo "============"
}

configure_time_sync() {
echo "============"
echo "开始配置时间同步"
echo "============"

yum install -y chrony || handle_error "Failed to install chrony"
systemctl start chronyd || handle_error "Failed to start chronyd"
systemctl enable chronyd || handle_error "Failed to enable chronyd"
sleep 4
chronyc sources || handle_error "Failed to check time synchronization sources"

echo "============"
echo "时间同步成功!"
echo "============"
}

update_hosts() {
echo "============"
echo "开始更新 /etc/hosts 文件"
echo "============"

for IP in "${!K8S_HOST_ENTRIES[@]}"; do
local HOSTNAME=${K8S_HOST_ENTRIES[$IP]}
if ! grep -q "$IP $HOSTNAME" /etc/hosts; then
echo "$IP $HOSTNAME" >> /etc/hosts || handle_error "Failed to update /etc/hosts with $IP $HOSTNAME"
echo "/etc/hosts updated with $IP $HOSTNAME"
else
echo "/etc/hosts already contains $IP $HOSTNAME"
fi
done

echo "============"
echo "更新 /etc/hosts 文件 成功!"
echo "============"
}

disable_swap() {
echo "============"
echo "开始关闭 Swap"
echo "============"

swapoff -a || handle_error "Failed to turn off swap"
sed -ri 's/.*swap.*/#&/' /etc/fstab || handle_error "Failed to update /etc/fstab for swap"

echo "============"
echo "Swap 关闭成功!"
echo "============"
}

disable_firewalld() {
echo "============"
echo "开始关闭防火墙"
echo "============"

systemctl stop firewalld || handle_error "Failed to stop firewalld"
systemctl disable firewalld || handle_error "Failed to disable firewalld"

echo "============"
echo "防火墙关闭成功!"
echo "============"
}

disable_selinux() {
echo "============"
echo "开始关闭 SELinux"
echo "============"

setenforce 0 || handle_error "Failed to set SELinux to permissive mode"
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config || handle_error "Failed to update /etc/selinux/config"

echo "============"
echo "SELinux 关闭成功!"
echo "============"
}

configure_iptables() {
echo "============"
echo "开始配置 Iptables"
echo "============"

if ! command -v yum &> /dev/null; then
handle_error "yum command not found"
fi

if [ "$(id -u)" -ne 0 ]; then
handle_error "This script must be run as root"
fi

yum install -y ipset ipvsadm || handle_error "Failed to install ipset"

IPTABLES_MODULES_CONF="/etc/modules-load.d/k8s.conf"
IPTABLES_SYSCTL_CONF="/etc/sysctl.d/k8s.conf"

cat <<EOF | tee "$IPTABLES_MODULES_CONF"
overlay
br_netfilter
EOF

for module in overlay br_netfilter ip_vs ip_vs_sh ip_vs_rr ip_vs_wrr nf_conntrack; do
modprobe "$module" || handle_error "Failed to load $module module"
done

cat <<EOF | tee "$IPTABLES_SYSCTL_CONF"
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF

sysctl --system || handle_error "Failed to apply sysctl settings"

lsmod | grep -E 'overlay|br_netfilter' || handle_error "Required iptables modules are not loaded"

sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward || handle_error "Failed to verify sysctl settings"

# 配置 kubelet
if [ -f /etc/sysconfig/kubelet ]; then
cat >> /etc/sysconfig/kubelet << EOF
# KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"
KUBE_PROXY_MODE="ipvs"
EOF
else
handle_error "/etc/sysconfig/kubelet file not found"
fi

echo "============"
echo "Iptables 配置成功!"
echo "============"
}

configure_docker() {
echo "============"
echo "开始配置 Docker Cgroup 驱动"
echo "============"

DOCKER_CONFIG_FILE="/etc/docker/daemon.json"

cat > "$DOCKER_CONFIG_FILE" << EOF
{
"registry-mirrors": ["$DOCKER_MIRROR_URL", "https://registry.docker-cn.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

systemctl restart docker || handle_error "Docker 重启失败"

echo "============"
echo "Docker Cgroup 配置驱动成功!"
echo "============"
}

configure_containerd() {
echo "============"
echo "开始配置 Containerd"
echo "============"

sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee "$CONTAINERD_CONFIG_FILE"

# 修改配置文件中的默认值
sed -i 's/SystemdCgroup\ =\ false/SystemdCgroup\ =\ true/g' "$CONTAINERD_CONFIG_FILE"
sed -i 's/sandbox_image\ =.*/sandbox_image\ =\ "registry.aliyuncs.com\/google_containers\/pause:3.9"/g' "$CONTAINERD_CONFIG_FILE"
sed -i 's/config_path\ =.*/config_path = \"\/etc\/containerd\/certs.d\"/g' "$CONTAINERD_CONFIG_FILE"

# 添加镜像加速器
mkdir -p /etc/containerd/certs.d/docker.io
cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"
[host."$DOCKER_MIRROR_URL"]
capabilities = ["pull", "resolve"]
EOF

echo "============"
echo "配置 Containerd 成功!"
echo "============"

echo "============"
echo "开始重启 Containerd"
echo "============"

systemctl daemon-reload
systemctl enable containerd || handle_error "Containerd 执行 systemctl enable containerd 时失败"
systemctl restart containerd || handle_error "Containerd 执行 systemctl restart containerd 时失败"

echo "============"
echo "Containerd 重启成功!"
echo "============"

# 验证 /run/containerd/containerd.sock 是否存在
if [ ! -S /run/containerd/containerd.sock ]; then
handle_error "/run/containerd/containerd.sock Sock 文件不存在. Containerd 可能没有正确启动!!"
fi
}

configure_crictl() {
echo "============"
echo "开始配置 CriCtl"
echo "============"

CRICTL_CONFIG_FILE="/etc/crictl.yaml"

if [ -f "${CRICTL_CONFIG_FILE}" ]; then
cat >> "${CRICTL_CONFIG_FILE}" << EOF
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: true
EOF
else
cat > "${CRICTL_CONFIG_FILE}" << EOF
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: true
EOF
fi

echo "============"
echo "CriCtl 配置成功!"
echo "============"

echo "============"
echo "开始重启 Containerd"
echo "============"

sudo systemctl restart containerd || handle_error "Containerd 重启失败!"

echo "============"
echo "Containerd 重启成功!"
echo "============"
}

main() {
echo "============"
echo "开始执行脚本"
echo "============"

check_root
set_hostname "$1"
configure_time_sync
update_hosts
disable_swap
disable_firewalld
disable_selinux
configure_iptables
configure_docker
configure_containerd
configure_crictl

echo "============"
echo "脚本执行完成"
echo "============"
}

main "$@"

2. 通过 scp 发送到目标机器

scp prepare_kubernetes.sh root@192.168.105.132:/root

3. 赋予脚本执行权限

chmod +x prepare_kubernetes.sh

4. 运行脚本

sudo ./prepare_kubernetes.sh <hostname>

sudo ./prepare_kubernetes.sh k8s-master
sudo ./prepare_kubernetes.sh k8s-node1
sudo ./prepare_kubernetes.sh k8s-node2

三、初始化 Master 节点


3.1 查看版本

# 1. 查看 kubeadm 版本
kubeadm version

# 2. 查看 kubelet 版本
kubelet --version

# 3. 查看 kubectl 版本
kubectl version --client

3.2 生成默认配置文件

kubeadm config print init-defaults > kubeadm.yaml

3.3 修改默认配置文件

vim kubeadm.yaml

1. 修改 advertiseAddress: xxxx 为宿主机 IP

advertiseAddress: 192.168.105.132  # 修改为宿主机ip

2. 修改 nodeRegistration 中的 name 为宿主机名

nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: k8s-master
taints: null

3. 修改 imageRepository 为阿里云镜像

imageRepository: registry.aliyuncs.com/google_containers

4. 修改 kubernetesVersionkubeadm 版本号

kubernetesVersion: 1.30.4  # kubeadm的版本为多少这里就修改为多少

5. 修改 networking 中的 podSubnet

networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16 ## 设置pod网段

6. 追加如下内容,关于 kubeletCGroup 配置

---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

3.4 下载所有镜像文件

kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers  --kubernetes-version=v1.30.4

3.5 开始进行初始化操作

kubeadm init --config kubeadm.yaml

3.6 将以上操作沉淀为脚本

1. 沉淀脚本,并命名为 init_kubernetes.sh

#!/bin/bash

set -e # 当有命令出错时,停止脚本的执行

# 全局变量
POD_SUBNET="10.244.0.0/16" # Pod 子网段
KUBERNETES_VERSION="1.30.4" # kubeadm 的版本号
MASTER_NODE_NAME="k8s-master" # 主节点的主机名
ADVERTISE_ADDRESS="192.168.105.132" # 主节点的 IP 地址
KUBEADM_CONFIG_FILE="kubeadm.yaml" # kubeadm 配置文件
IMAGE_REPOSITORY="registry.aliyuncs.com/google_containers" # 使用的镜像仓库

reset_kubernetes() {
echo "============"
echo "开始重置 Kubernetes"
echo "============"

kubeadm reset -f || handle_error "Failed to reset Kubernetes"

echo "============"
echo "重置 Kubernetes 成功!"
echo "============"
}

generate_default_config() {
echo "============"
echo "开始生成 默认的 kubeadm 配置文件"
echo "============"

kubeadm config print init-defaults > "$KUBEADM_CONFIG_FILE"

echo "============"
echo "默认的 kubeadm 配置文件生成成功!"
echo "============"
}

modify_config_file() {
echo "============"
echo "开始修改 默认的 kubeadm 配置文件"
echo "============"

# 修改 advertiseAddress
sed -i "s|^\(\s*advertiseAddress:\s*\).*|\1$ADVERTISE_ADDRESS|" "$KUBEADM_CONFIG_FILE"

# 修改 nodeRegistration 的 name
sed -i "s|^\(\s*name:\s*\).*|\1$MASTER_NODE_NAME|" "$KUBEADM_CONFIG_FILE"

# 修改 imageRepository
sed -i "s|^\(\s*imageRepository:\s*\).*|\1$IMAGE_REPOSITORY|" "$KUBEADM_CONFIG_FILE"

# 修改 kubernetesVersion
sed -i "s|^\(\s*kubernetesVersion:\s*\).*|\1$KUBERNETES_VERSION|" "$KUBEADM_CONFIG_FILE"

# 检查 networking 下是否有 podSubnet 属性
if ! grep -q "^\s*podSubnet:" "$KUBEADM_CONFIG_FILE"; then
# 如果没有 podSubnet 属性,添加它
sed -i "/^\s*networking:/a\ podSubnet: $POD_SUBNET" "$KUBEADM_CONFIG_FILE"
else
# 如果有 podSubnet 属性,修改它
sed -i "s|^\(\s*podSubnet:\s*\).*|\1$POD_SUBNET|" "$KUBEADM_CONFIG_FILE"
fi

# 追加 kubelet 的 CGroup 配置
cat >> "$KUBEADM_CONFIG_FILE" <<EOF
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd
EOF

echo "============"
echo "修改 默认的 kubeadm 配置文件成功!"
echo "============"
}

pull_required_images() {
echo "============"
echo "开始下载所需的镜像文件"
echo "============"

kubeadm config images pull --image-repository="$IMAGE_REPOSITORY" --kubernetes-version="$KUBERNETES_VERSION"

echo "============"
echo "所需的镜像文件下载成功!"
echo "============"
}

initialize_master_node() {
echo "============"
echo "开始初始化 Kubernetes Master 节点"
echo "============"

kubeadm init --config "$KUBEADM_CONFIG_FILE"

echo "============"
echo "初始化 Kubernetes Master 节点成功!"
echo "============"
}

main() {
echo "============"
echo "开始执行脚本"
echo "============"

reset_kubernetes
generate_default_config
modify_config_file
pull_required_images
initialize_master_node

echo "============"
echo "开始执行完成"
echo "============"
}

main

2. 通过 scp 发送到目标机器

scp init_kubernetes.sh root@192.168.105.132:/root

3. 赋予脚本执行权限

chmod +x init_kubernetes.sh

4. 运行脚本

sudo ./init_kubernetes.sh

5. 出现下述输出,说明安装完成

Preview

3.7 初始化成功后运行命令

1. 按照控制台输出提示,在 Master 节点中执行上述图片中的命令

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
  1. 按照控制台输出提示,在 Master 节点中添加环境变量
# 设置环境变量
export KUBECONFIG=/etc/kubernetes/admin.conf
// 或者
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile

3. 查看此时 Master 节点状态

kubectl get node 

3.8 初始化成功后应用 Calico 网络插件

CalicoKubernetes 中常用的网络插件之一。 Calico 适合需要高性能网络和高级网络策略的大型集群,适用于对网络安全和灵活性要求较高的场景。特点如下:

  • 高性能Calico 使用基于路由的网络模式,不依赖覆盖网络,直接在主机网络上进行路由,性能较高。

  • 网络策略Calico 支持 Kubernetes 网络策略,可以实现细粒度的网络安全控制。

  • 灵活性Calico 可以与多种数据平面(如 BGPVXLAN)集成,提供灵活的网络配置选项。

  • 复杂性:由于功能强大,Calico 的配置和管理相对复杂,适合有一定经验的用户。

Kubernetes 应用 Calico 网络插件的操作如下:

1. 下载 Calico 网络插件: 在 M1 Mac 上下载 calico.yaml 配置文件,并传输到 VMFunction Centos8 ARM 64

# 1. M1 Mac 获取下载地址 
浏览器访问 https://docs.projectcalico.org/manifests/calico.yaml 会发生重定向,复制重定向之后的地址

# 2. M1 Mac 下载 calico.yaml
curl -O https://calico-v3-25.netlify.app/archive/v3.25/manifests/calico.yaml

# 3. M1 Mac 传输到 VMFunciton Centos8 ARM 64
scp calico.yaml root@192.168.105.132:/root

# 4. VMFunciton Centos8 ARM 64 移动 calico.yaml/tmp 目录下
mv calico.yaml /tmp

2. 查看 Calico 配置文件 /tmp/calico.yaml 依赖镜像: 在 /tmp/calico.yaml 中搜索 image 关键词即可

cat /tmp/calico.yaml
- name: upgrade-ipam
image: docker.io/calico/cni:v3.25.0
imagePullPolicy: IfNotPresent

- name: calico-node
image: docker.io/calico/node:v3.25.0
imagePullPolicy: IfNotPresent

containers:
- name: calico-kube-controllers
image: docker.io/calico/kube-controllers:v3.25.0
imagePullPolicy: IfNotPresent

3. 下载并上传所需镜像: 在可科学上网的机器上下载 arm64 镜像,并上传到阿里云个人镜像仓库。

# cni
docker pull --platform linux/arm64 docker.io/calico/cni:v3.25.0

docker inspect calico/cni:v3.25.0 | grep Architecture

docker tag calico/cni:v3.25.0 registry.cn-hangzhou.aliyuncs.com/bolawen/calico-cni:v3.25.0-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/calico-cni:v3.25.0-linux-arm64

# node

docker pull --platform linux/arm64 docker.io/calico/node:v3.25.0

docker inspect calico/node:v3.25.0 | grep Architecture

docker tag calico/node:v3.25.0 registry.cn-hangzhou.aliyuncs.com/bolawen/calico-node:v3.25.0-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/calico-node:v3.25.0-linux-arm64

# kube-controllers
docker pull --platform linux/arm64 docker.io/calico/kube-controllers:v3.25.0

docker inspect calico/kube-controllers:v3.25.0 | grep Architecture

docker tag calico/kube-controllers:v3.25.0 registry.cn-hangzhou.aliyuncs.com/bolawen/calico-kube-controllers:v3.25.0-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/calico-kube-controllers:v3.25.0-linux-arm64

4. 配置 /tmp/calico.yaml

sed -i -e 's|docker.io/calico/cni:v3.25.0|registry.cn-hangzhou.aliyuncs.com/bolawen/calico-cni:v3.25.0-linux-arm64|g' \
-e 's|docker.io/calico/node:v3.25.0|registry.cn-hangzhou.aliyuncs.com/bolawen/calico-node:v3.25.0-linux-arm64|g' \
-e 's|docker.io/calico/kube-controllers:v3.25.0|registry.cn-hangzhou.aliyuncs.com/bolawen/calico-kube-controllers:v3.25.0-linux-arm64|g' /tmp/calico.yaml

5. 应用 calico.yml 配置

# 如果之前未安装过 Calico
sudo kubectl apply -f /tmp/calico.yaml
# 如果之前已经安装过 Calico 
sudo kubectl delete -f /tmp/calico.yaml
sudo kubectl apply -f /tmp/calico.yaml

6. 验证 calico 网络插件

# 查看 calico 各个服务状态
kubectl get pods --namespace kube-system

# 查看 calico-xxx Pod 的日志
kubectl logs --namespace kube-system <pod-name>

# 查看 calico-xxx Pod 的详细描述
kubectl describe pod <pod-name> --namespace kube-system

看到如下信息时,说明安装成功!

NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-xxxxxx-xxxxx 1/1 Running 0 1m
calico-node-xxxxxx-xxxxx 1/1 Running 0 1m

7. 查看此时 Master 节点状态

kubectl get node 

3.9 初始化成功后部署 Dashborard 仪表盘

Dashboard 是基于网页的 Kubernetes 用户界面。 你可以使用 Dashboard 将容器应用部署到 Kubernetes 集群中,也可以对容器应用排错,还能管理集群资源。 你可以使用 Dashboard 获取运行在集群中的应用的概览信息,也可以创建或者修改 Kubernetes 资源 (如 DeploymentJobDaemonSet 等等)。 例如,你可以对 Deployment 实现弹性伸缩、发起滚动升级、重启 Pod 或者使用向导创建新的应用。Dashboard 同时展示了 Kubernetes 集群中的资源状态信息和所有报错信息。Dashboard 安装部署如下:

1. 安装 Helm 包管理器: 在 M1 Mac 上下载 get_helm.sh,并传输到 VMFunction Centos8 ARM 64HelmKubernetes 的包管理器。

# 1. M1 Mac 下载  get_helm.sh
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3

# 2. M1 Mac 将 get_helm.sh 传输到 VMFunciton Centos8 ARM 64
scp get_helm.sh root@192.168.105.135:/root

# 3. VMFunciton Centos8 ARM 64 执行如下命令
chmod 700 get_helm.sh
sudo ./get_helm.sh

# 4. VMFunciton Centos8 ARM 64 测试 helm
heml version
helm repo list

2. 下载 Dashboard 安装包并生成 values.yaml 配置文件: 在 M1 Mac 上下载 kubernetes-dashboard.tgz 文件,并传输到 VMFunction Centos8 ARM 64。然后在 M1 Mac 上使用 helm 生成 values.yaml 配置文件,并传输到 VMFunction Centos8 ARM 64

# 1. M1 Mac 选择对应版本下载
wget https://github.com/kubernetes/dashboard/releases/download/kubernetes-dashboard-7.5.0/kubernetes-dashboard-7.5.0.tgz

# 2. M1 Mac 上安装 helm
brew install helm

# 3. M1 Mac helm 添加 kubernetes-dashboard 仓库
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm repo list

# 4. M1 Mac 通过 helm 生成 values.yaml 配置文件
helm show values kubernetes-dashboard/kubernetes-dashboard > values.yaml

# 5. M1 Mac 将 values.yaml 传输到 VMFunciton Centos8 ARM 64
scp values.yaml root@192.168.105.132:/root

# 6. M1 Mac 将 kubernetes-dashboard-7.5.0.tgz 传输到 VMFunciton Centos8 ARM 64
scp kubernetes-dashboard-7.5.0.tgz root@192.168.105.132:/root

3. 查看 Dashboard 配置文件 values.yaml 依赖镜像: 在 values.yaml 中搜索 image 关键词即可

cat values.yaml 
auth:
role: auth
image:
repository: docker.io/kubernetesui/dashboard-auth
tag: 1.1.3

api:
role: api
image:
repository: docker.io/kubernetesui/dashboard-api
tag: 1.7.0

web:
role: web
image:
repository: docker.io/kubernetesui/dashboard-web
tag: 1.4.0

metricsScraper:
enabled: true
role: metrics-scraper
image:
repository: docker.io/kubernetesui/dashboard-metrics-scraper
tag: 1.1.1

# 隐藏的一个镜像
docker.io/library/kong:3.6

4. 查看 kubernetes-dashboard/charts/kong/values.yaml 依赖镜像: 在 M1 Mac 上解压 kubernetes-dashboard-7.5.0.tgz,查看 kubernetes-dashboard/charts/kong/values.yaml 文件中的依赖镜像。该文件包含两个需要下载的镜像。

# 1. M1 Mac 解压 kubernetes-dashboard-7.5.0.tgz 
tar -zxvf kubernetes-dashboard-7.5.0.tgz

# 2. M1 Mac 查看 kubernetes-dashboard/charts/kong/values.yaml 依赖镜像
code kubernetes-dashboard/charts/kong/values.yaml
image:
repository: kong
tag: "3.6"

ingressController:
enabled: true
image:
repository: kong/kubernetes-ingress-controller
tag: "3.1"

5. 下载并上传所需镜像: 在可科学上网的机器上下载 arm64 镜像,并上传到阿里云个人镜像仓库。

# dashboard-auth:1.1.3
docker pull --platform linux/arm64 docker.io/kubernetesui/dashboard-auth:1.1.3

docker inspect kubernetesui/dashboard-auth:1.1.3 | grep Architecture

docker tag kubernetesui/dashboard-auth:1.1.3 registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-auth:1.1.3-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-auth:1.1.3-linux-arm64


# dashboard-api:1.7.0
docker pull --platform linux/arm64 docker.io/kubernetesui/dashboard-api:1.7.0

docker inspect kubernetesui/dashboard-api:1.7.0 | grep Architecture

docker tag kubernetesui/dashboard-api:1.7.0 registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-api:1.7.0-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-api:1.7.0-linux-arm64

# dashboard-web:1.4.0
docker pull --platform linux/arm64 docker.io/kubernetesui/dashboard-web:1.4.0

docker inspect kubernetesui/kubernetesui/dashboard-web:1.4.0 | grep Architecture

docker tag kubernetesui/dashboard-web:1.4.0 registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-web:1.4.0-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-web:1.4.0-linux-arm64

# dashboard-metrics-scraper:1.1.1
docker pull --platform linux/arm64 docker.io/kubernetesui/dashboard-metrics-scraper:1.1.1

docker inspect kubernetesui/kubernetesui/dashboard-metrics-scraper:1.1.1 | grep Architecture

docker tag kubernetesui/dashboard-metrics-scraper:1.1.1 registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-metrics-scraper:1.1.1-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/dashboard-metrics-scraper:1.1.1-linux-arm64

# kong:3.6
docker pull --platform linux/arm64 docker.io/library/kong:3.6
docker tag docker.io/library/kong:3.6 registry.cn-hangzhou.aliyuncs.com/bolawen/kong:3.6-linux-arm64
docker push registry.cn-hangzhou.aliyuncs.com/bolawen/kong:3.6-linux-arm64

# kong/kubernetes-ingress-controller:3.1
docker pull --platform linux/arm64 kong/kubernetes-ingress-controller:3.1.0

docker tag kong/kubernetes-ingress-controller:3.1.0 registry.cn-hangzhou.aliyuncs.com/bolawen/kong-kubernetes-ingress-controller:3.1.0-linux-arm64

docker push registry.cn-hangzhou.aliyuncs.com/bolawen/kong-kubernetes-ingress-controller:3.1.0-linux-arm64

6. 配置 values.yaml: 将 image.repositoryimage.tag 替换为阿里云上的镜像地址和 arm64 版本。

# VMFunciton Centos8 ARM 64
sed -i -e 's|docker.io/kubernetesui|registry.cn-hangzhou.aliyuncs.com/bolawen|g' \
-e 's|tag: 1.1.3|tag: 1.1.3-linux-arm64|g' \
-e 's|tag: 1.7.0|tag: 1.7.0-linux-arm64|g' \
-e 's|tag: 1.4.0|tag: 1.4.0-linux-arm64|g' \
-e 's|tag: 1.1.1|tag: 1.1.1-linux-arm64|g' values.yaml

7. 配置 kubernetes-dashboard/charts/kong/values.yaml: 将 image.repositoryimage.tag 替换为阿里云上的镜像地址和 arm64 版本。

# M1 Mac 
sed -i '' -e 's|repository: kong|repository: registry.cn-hangzhou.aliyuncs.com/bolawen/kong|g' \
-e 's|repository: kong/kubernetes-ingress-controller$|repository: registry.cn-hangzhou.aliyuncs.com/bolawen/ kong-kubernetes-ingress-controller|g' \
-e 's|tag: "3.6"|tag: "3.6-linux-arm64"|g' \
-e 's|tag: "3.1"|tag: "3.1:3.1.0-linux-arm64"|g' kubernetes-dashboard/charts/kong/values.yaml

8. 重新打包 kubernetes-dashboard-7.5.0.tgz: M1 Mac 上重新将 kubernetes-dashboard 打包为 kubernetes-dashboard-7.5.0.tgz, 并传输到 VMFunction Centos8 ARM 64

# 1. 重新打包 kubernetes-dashboard-7.5.0.tgz
tar -zcvf kubernetes-dashboard-7.5.0.tgz kubernetes-dashboard/

# 2. M1 Mac 传输到 VMFunction Centos8 ARM 64
scp kubernetes-dashboard-7.5.0.tgz root@192.168.105.132:/root

9. 通过 Helm 安装部署 Dashborard

# 如果之前未安装过
helm upgrade --install kubernetes-dashboard kubernetes-dashboard-7.5.0.tgz --create-namespace --namespace kubernetes-dashboard -f values.yaml
# 如果之前已经安装过

helm uninstall kubernetes-dashboard --namespace kubernetes-dashboard

helm list --namespace kubernetes-dashboard

helm upgrade --install kubernetes-dashboard kubernetes-dashboard-7.5.0.tgz --create-namespace --namespace kubernetes-dashboard -f values.yaml

10. 验证 Dashborard 状态

# 查看 kubernetes-dashboard 各个服务状态
kubectl get svc --namespace kubernetes-dashboard
kubectl get pods --namespace kubernetes-dashboard

# 查看 kubernetes-dashboard-xxx Pod 的日志
kubectl logs --namespace kubernetes-dashboard <pod-name>

# 查看 kubernetes-dashboard-xxx Pod 的详细描述
kubectl describe pod --namespace kubernetes-dashboard <pod-name>

# 检测 kubernetes-dashboard 的资源配置(如 CPU 和内存)足够
kubectl get pod <pod-name> -n kubernetes-dashboard -o yaml

11. 编辑 Dashborard 各个组件

# 查看 kubernetes-dashboard 各个组件服务
kubectl get svc --namespace kubernetes-dashboard

# 编辑 kubernetes-dashboard 各个组件服务
kubectl edit svc kubernetes-dashboard-api --namespace kubernetes-dashboard // 编辑 TYPE 为 NodePort
kubectl edit svc kubernetes-dashboard-auth --namespace kubernetes-dashboard // 编辑 TYPE 为 NodePort
kubectl edit svc kubernetes-dashboard-kong-manager --namespace kubernetes-dashboard // 编辑 TYPE 为 NodePort
……
kubectl edit svc kubernetes-dashboard-web --namespace kubernetes-dashboard // 编辑 TYPE 为 NodePort

# 再次查看 kubernetes-dashboard 各个组件服务

kubectl get svc --namespace kubernetes-dashboard

12. 创建 Dashborard 用户: Dashborard 用户文档地址

# 创建 dashboard-adminuser.yaml 文件
vim dashboard-adminuser.yaml
# dashboard-adminuser.yaml 文件内容
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
name: admin-user
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: "admin-user"
type: kubernetes.io/service-account-token

13. 应用 dashboard-adminuser.yaml 配置

kubectl apply -f dashboard-adminuser.yaml

14. 获取 Dashborard Token

kubectl -n kubernetes-dashboard create token admin-user

15. 访问 Dashborard: 本文是 M1 Mac + VMFunciton Centos8 ARM 64, 在 VMFunciton Centos8 ARM 64 上部署 Kubernetes Dashboard, 经过 kubectl edit svc 编辑 Kubernetes Dashboard 各个组件 TypeNodePort 。然后在 M1 Mac 上进行访问, 访问地址如下:

# 格式
http://VMFunciton Centos8 ARM 64 IP地址:kubernetes-dashboard-web Port

# 举例
http://192.168.105.132:31008

四、初始化 Worker 节点


4.1 Workder 节点加入 Master 集群

Worker 节点上, 基于 kubeadm join 加入 Master 节点集群: 如果不小心把 kubeadm join 命令清屏了,使用:kubeadm token create --print-join-command 重新生成

kubeadm join 192.168.105.132:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:e34da279d1bc8dd0ef0ee8f4c3f934865e79fa489b9ee45b409ce3794de728b5

4.2 验证 Wroker 节点与 Master 集群

Master 节点上,通过 kubectl get nodes 查看 Worker 节点状态

kubectl get nodes

或者

kubectl get pod -A

或者

kubectl get pods -n kube-system

参考资料


部署kubernetes-v1.25.3(k8s)- 基于containerd容器运行时