基于 openEuler 24.03 LTS 操作系统源码部署 Kubernetes 开发版本
1 安装目标使用源码编译安装 Kubernetes，可以方便的切换版本，方便开发测试工作。本文以 openEuler 24.03 LTS 系统作为基础环境，演示如何操作2 环境准备2.1 网络环境由于编译 docker 所需的源代码资源都在外网，因此需要提前配置代理# 配置代理 PROXY_IP=192.168.230.1 PROXY_PORT=10809 export http_proxy=http://${PROXY_IP}:${PROXY_PORT} export https_proxy=http://${PROXY_IP}:${PROXY_PORT} export ALL_PROXY=http://${PROXY_IP}:${PROXY_PORT} export all_proxy=socks://${PROXY_IP}:${PROXY_PORT} # 测试代理 $ curl www.google.com2.2 系统环境（1）设置主机名及域名解析# 设置主机名 $ hostnamectl set-hostname k8s-master # 配置域名解析 $ cat >>/etc/hosts <<EOF 192.168.230.240 k8s-master EOF（2）关闭防火墙及 SELinux# 关闭防火墙 $ systemctl stop firewalld && systemctl disable firewalld # 关闭 SELinux $ setenforce 0 && sed -i 's/\(SELINUX=\).*/\1disabled/' /etc/selinux/config（3）关闭 Swap 分区# 关闭 Swap 分区 $ swapoff -a # 禁止开机自动挂载 Swap 分区 $ sed -i '/swap/ s/^\(.*\)$/#\1/g' /etc/fstab（4）加载 netfilter 模块# 加载 netfilter 模块 $ modprobe br_netfilter && lsmod | grep br_netfilter br_netfilter 36864 0 bridge 397312 1 br_netfilter # 设置开机自动加载 netfilter 模块 $ cat >/etc/modules-load.d/br_netfilter.conf <<EOF br_netfilter EOF（5）调整内核参数# 编写配置文件 $ cat > /etc/sysctl.d/kubernetes.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 vm.max_map_count = 262144 EOF # 加载配置文件 $ sysctl -p /etc/sysctl.d/kubernetes.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 vm.max_map_count = 2621442.3 工具环境（1）安装编译及其他工具# 安装编译工具 $ yum install -y gcc-c++ make rsync lxcfs # 启动 lxcfs $ systemctl start lxcfs && systemctl enable lxcfs（2）安装 cfssl 工具# 下载 cfssl 工具 $ wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64 -P /root # 安装 cfssl 工具 $ mv /root/cfssl_1.6.5_linux_amd64 /usr/local/bin/cfssl && chmod +x /usr/local/bin/cfssl # 测试 cfssl 工具 $ cfssl version Version: 1.6.5 Runtime: go1.22.0 # 下载 cfssljson 工具 $ wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64 -P /root # 安装 cfssljson 工具 $ mv /root/cfssljson_1.6.5_linux_amd64 /usr/local/bin/cfssljson && chmod +x /usr/local/bin/cfssljson # 测试 cfssl 工具 $ cfssljson -version Version: 1.6.5 Runtime: go1.22.02.4 go 环境（1）配置环境变量# 配置环境变量 $ cat >> /etc/profile <<"EOF" export GOPATH=/root/go export GOBIN=${GOPATH}/bin export GOROOT=/usr/local/go export PATH=${PATH}:${GOROOT}/bin EOF # 重载环境变量 $ source /etc/profile（2）安装 go 二进制包# 下载 go 二进制包 $ wget https://golang.google.cn/dl/go1.20.8.linux-amd64.tar.gz -P /root --2024-12-01 12:47:12-- https://golang.google.cn/dl/go1.20.8.linux-amd64.tar.gz Connecting to 192.168.230.1:10809... connected. Proxy request sent, awaiting response... 302 Found Location: https://dl.google.com/go/go1.20.8.linux-amd64.tar.gz [following] --2024-12-01 12:47:12-- https://dl.google.com/go/go1.20.8.linux-amd64.tar.gz Connecting to 192.168.230.1:10809... connected. Proxy request sent, awaiting response... 200 OK Length: 100431921 (96M) [application/x-gzip] Saving to: ‘/root/go1.20.8.linux-amd64.tar.gz’ go1.20.8.linux-amd64.tar. 100%[=============>] 95.78M 11.2MB/s in 8.8s 2024-12-01 12:47:21 (10.9 MB/s) - ‘/root/go1.20.8.linux-amd64.tar.gz’ saved [100431921/100431921] # 解压二进制包 $ rm -rf /usr/local/go && tar -zxvf go1.20.8.linux-amd64.tar.gz -C /usr/local # 查看 go 版本 $ go version go version go1.20.8 linux/amd642.5 容器环境（1）安装配置 Docker# 安装 docker $ yum install -y docker # 启动 docker $ systemctl start docker && systemctl enable docker # 创建服务配置目录 $ mkdir -p /etc/systemd/system/docker.service.d # 配置代理 $ cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF [Service] Environment="HTTP_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="HTTPS_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="NO_PROXY=localhost,127.0.0.1" EOF # 重新加载配置 $ systemctl daemon-reload # 重启 docker $ systemctl restart docker # 查看代理是否配置成功 $ docker info | grep Proxy HTTP Proxy: http://192.168.230.1:10809 HTTPS Proxy: http://192.168.230.1:10809 No Proxy: localhost,127.0.0.1 # 测试拉取镜像 $ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world c1ec31eb5944: Pull complete Digest: sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. ......（2）安装配置 CRI-Dockerd2022 年 5 月 3 日，Kubernetes 1.24 版本正式发布，该版本 Kubernetes 正式移除对 Dockershim 的支持（参考文档：Kubernetes容器运行时弃用Docker转型Containerd | i4T）。因此，若还使用 Docker 作为容器运行时，则需要手动安装 CRI-Dockerd，或者使用 Containerd 作为容器运行时（安装方法见附录）# 下载 cri-dockerd $ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.15/cri-dockerd-0.3.15.amd64.tgz -P /root # 解压下载的压缩包 $ tar -xvf /root/cri-dockerd-0.3.15.amd64.tgz cri-dockerd/ cri-dockerd/cri-dockerd # 复制命令到 /usr/bin/ 目录，并添加可执行权限 $ cp /root/cri-dockerd/cri-dockerd /usr/bin/ && chmod +x /usr/bin/cri-dockerd # 编写 cri-docker.service 文件 $ cat > /etc/systemd/system/cri-dockerd.service <<"EOF" [Unit] Description=CRI Interface for Docker Application Container Engine Documentation=https://docs.mirantis.com After=network-online.target firewalld.service docker.service Wants=network-online.target Requires=cri-dockerd.socket [Service] Type=notify ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.k8s.io/pause:3.8 ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always StartLimitBurst=3 StartLimitInterval=60s LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity Delegate=yes KillMode=process [Install] WantedBy=multi-user.target EOF # 编写 cri-docker.socket 文件 $ cat > /usr/lib/systemd/system/cri-dockerd.socket <<"EOF" [Unit] Description=CRI Docker Socket for the API PartOf=cri-dockerd.service [Socket] ListenStream=%t/cri-dockerd.sock SocketMode=0660 SocketUser=root SocketGroup=docker [Install] WantedBy=sockets.target EOF # 重载配置文件 $ systemctl daemon-reload # 启动 cri-docker 并设置开机自启 $ systemctl start cri-dockerd && systemctl enable cri-dockerd Created symlink /etc/systemd/system/multi-user.target.wants/cri-dockerd.service → /etc/systemd/system/cri-dockerd.service. # 查看 cri-docker 状态 $ systemctl status cri-dockerd ● cri-dockerd.service - CRI Interface for Docker Application Container Engine Loaded: loaded (/etc/systemd/system/cri-dockerd.service; enabled; preset: disabled) Active: active (running) since Mon 2024-12-02 08:40:30 CST; 6s ago TriggeredBy: ● cri-dockerd.socket Docs: https://docs.mirantis.com Main PID: 2655 (cri-dockerd) Tasks: 10 Memory: 10.6M () CGroup: /system.slice/cri-dockerd.service └─2655 /usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.k8s.io/pause:3.8 ..... # 查看套接字文件，调用方法：unix:///run/cri-dockerd.sock $ ls -l /run/cri-dockerd.sock srwxr-xr-x 1 root root 0 Dec 2 08:40 /run/cri-dockerd.sock3 编译安装 Kubernetes3.1 编译 Kubernetes# 创建存放源代码的目录 $ mkdir -p ${GOPATH}/src/kubernetes # 进入源代码目录 $ cd ${GOPATH}/src/kubernetes # 克隆 Kubernetes 源代码 $ git clone https://github.com/kubernetes/kubernetes Cloning into 'kubernetes'... remote: Enumerating objects: 1593137, done. remote: Counting objects: 100% (47/47), done. remote: Compressing objects: 100% (38/38), done. remote: Total 1593137 (delta 12), reused 33 (delta 8), pack-reused 1593090 (from 1) Receiving objects: 100% (1593137/1593137), 1.05 GiB | 16.23 MiB/s, done. Resolving deltas: 100% (1166449/1166449), done. Updating files: 100% (26242/26242), done. # 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 查看所有版本分支 $ git ls-remote --tags origin # 将 Kubernetes 切换到需要的版本 $ git checkout v1.29.11 Updating files: 100% (15331/15331), done. Note: switching to 'v1.29.11'. ...... # 执行编译命令，编译所有工具 $ KUBE_BUILD_PLATFORMS="$(go env GOHOSTOS)/$(go env GOHOSTARCH)" make all GOFLAGS=-v GOGCFLAGS="-N -l" # 查看编译生成的命令 $ ls -l ./_output/local/bin/linux/amd64 total 1152540 -rwxr-xr-x 1 root root 61943960 Dec 2 08:55 apiextensions-apiserver -rwxr-xr-x 1 root root 147363496 Dec 2 08:55 e2e_node.test -rwxr-xr-x 1 root root 169920112 Dec 2 08:55 e2e.test -rwxr-xr-x 1 root root 9294084 Dec 2 08:55 ginkgo -rwxr-xr-x 1 root root 1908996 Dec 2 08:55 go-runner -rwxr-xr-x 1 root root 48709784 Dec 2 08:55 kubeadm -rwxr-xr-x 1 root root 59478168 Dec 2 08:55 kube-aggregator -rwxr-xr-x 1 root root 124129432 Dec 2 08:55 kube-apiserver -rwxr-xr-x 1 root root 119271576 Dec 2 08:55 kube-controller-manager -rwxr-xr-x 1 root root 50225304 Dec 2 08:55 kubectl -rwxr-xr-x 1 root root 48554136 Dec 2 08:55 kubectl-convert -rwxr-xr-x 1 root root 112603396 Dec 2 08:55 kubelet -rwxr-xr-x 1 root root 1687704 Dec 2 08:55 kube-log-runner -rwxr-xr-x 1 root root 110997656 Dec 2 08:55 kubemark -rwxr-xr-x 1 root root 55877784 Dec 2 08:55 kube-proxy -rwxr-xr-x 1 root root 56565912 Dec 2 08:55 kube-scheduler -rwxr-xr-x 1 root root 1605784 Dec 2 08:55 mounter # 配置环境变量 $ sed -i '$a export PATH=${PATH}:${GOPATH}/src/kubernetes/kubernetes/_output/local/bin/linux/amd64' /etc/profile # 重载环境变量 $ source /etc/profile # 测试环境变量是否生效 $ kubeadm version kubeadm version: &version.Info{Major:"1", Minor:"29", GitVersion:"v1.29.11", GitCommit:"960a2f019319ab5f7ac1c256efcc180a4113343a", GitTreeState:"clean", BuildDate:"2024-12-02T00:49:59Z", GoVersion:"go1.22.8", Compiler:"gc", Platform:"linux/amd64"}说明：如果只想编译其中一个组件，例如只编译 kubelet，可以使用该命令：KUBE_BUILD_PLATFORMS="$(go env GOHOSTOS)/$(go env GOHOSTARCH)" make all WHAT=cmd/kubelet GOFLAGS=-v GOGCFLAGS="-N -l"3.2 安装 etcd# 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 执行安装脚本 $ ./hack/install-etcd.sh Downloading https://github.com/coreos/etcd/releases/download/v3.5.16/etcd-v3.5.16-linux-amd64.tar.gz succeed etcd v3.5.16 installed. To use: export PATH="/root/go/src/kubernetes/kubernetes/third_party/etcd:${PATH}" # 查看编译生成的命令 $ ls -l third_party/etcd/ total 55180 drwxr-xr-x 3 1000 1000 4096 Sep 11 02:22 Documentation -rwxr-xr-x 1 1000 1000 23621784 Sep 11 02:22 etcd -rwxr-xr-x 1 1000 1000 17899672 Sep 11 02:22 etcdctl -rwxr-xr-x 1 1000 1000 14893208 Sep 11 02:22 etcdutl -rw-r--r-- 1 1000 1000 42066 Sep 11 02:22 README-etcdctl.md -rw-r--r-- 1 1000 1000 7359 Sep 11 02:22 README-etcdutl.md -rw-r--r-- 1 1000 1000 9210 Sep 11 02:22 README.md -rw-r--r-- 1 1000 1000 7896 Sep 11 02:22 READMEv2-etcdctl.md # 配置环境变量 $ sed -i '$a export PATH=${PATH}:${GOPATH}/src/kubernetes/kubernetes/third_party/etcd' /etc/profile # 重载环境变量 $ source /etc/profile # 测试环境变量是否生效 $ etcd --version etcd Version: 3.5.16 Git SHA: f20bbad Go Version: go1.22.7 Go OS/Arch: linux/amd644 使用 Kubernetes4.1 启动 Kubernetes# 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 修改启动脚本中：允许特权容器运行、API 节点名称 $ sed -i \ -e '/^ALLOW_PRIVILEGED=/c ALLOW_PRIVILEGED=${ALLOW_PRIVILEGED:-"true"}' \ -e '/^HOSTNAME_OVERRIDE=/c HOSTNAME_OVERRIDE=${HOSTNAME_OVERRIDE:-"$(hostname)"}' \ ./hack/local-up-cluster.sh # 若 Kubernetes 版本大于等于 1.24，且使用 Docker 作为容器运行时，则还需要修改容器运行时的套接字 $ sed -i '/^CONTAINER_RUNTIME_ENDPOINT/c CONTAINER_RUNTIME_ENDPOINT=${CONTAINER_RUNTIME_ENDPOINT:-"unix:///run/cri-dockerd.sock"}' ./hack/local-up-cluster.sh # 执行启动脚本 $ ./hack/local-up-cluster.sh -O ...... To start using your cluster, you can open up another terminal/tab and run: export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig cluster/kubectl.sh Alternatively, you can write to the default kubeconfig: export KUBERNETES_PROVIDER=local cluster/kubectl.sh config set-cluster local --server=https://localhost:6443 --certificate-authority=/var/run/kubernetes/server-ca.crt cluster/kubectl.sh config set-credentials myself --client-key=/var/run/kubernetes/client-admin.key --client-certificate=/var/run/kubernetes/client-admin.crt cluster/kubectl.sh config set-context local --cluster=local --user=myself cluster/kubectl.sh config use-context local cluster/kubectl.sh ------------------------------以下步骤重新打开一个终端执行------------------------------ # 刷新环境变量 $ source /etc/profile # 声明连接 Kubernetes API 服务器信息的配置文件 $ export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig # 查看集群节点状态 $ kubectl get node NAME STATUS ROLES AGE VERSION k8s-master Ready <none> 10m v1.29.11-dirty4.2 安装 CalicoCalico 下载地址：https://github.com/projectcalico/calicoCalico 版本与 Kubernete 版本需要有对应关系，可参考文档：Documentation archive | Calico Documentation# 下载 calico $ wget https://github.com/projectcalico/calico/releases/download/v3.28.2/release-v3.28.2.tgz -P /root # 解压 calico $ tar -xvf /root/release-v3.28.2.tgz -C /root # 加载 calico 镜像 $ for img in $(ls /root/release-v3.28.2/images/*); do docker load -i "${img}"; done fc72e302317a: Loading layer [==========================>] 3.692MB/3.692MB 17f473a5550b: Loading layer [==========================>] 205.5MB/205.5MB 5f70bf18a086: Loading layer [==========================>] 1.024kB/1.024kB Loaded image: calico/cni:v3.28.2 4e9f7ac9fb07: Loading layer [==========================>] 38.33MB/38.33MB Loaded image: calico/dikastes:v3.28.2 3bdcbcc4896a: Loading layer [==========================>] 124.9MB/124.9MB Loaded image: calico/flannel-migration-controller:v3.28.2 b99a8e25f25e: Loading layer [==========================>] 75.3MB/75.3MB Loaded image: calico/kube-controllers:v3.28.2 31f1fc200f28: Loading layer [==========================>] 374.2MB/374.2MB Loaded image: calico/node:v3.28.2 03b5f1752b13: Loading layer [==========================>] 9.832MB/9.832MB Loaded image: calico/pod2daemon-flexvol:v3.28.2 67c02963f81a: Loading layer [==========================>] 67.58MB/67.58MB Loaded image: calico/typha:v3.28.2 # 获取 Pod 网络 $ grep "^CLUSTER_CIDR" ${GOPATH}/src/kubernetes/kubernetes/hack/local-up-cluster.sh | awk -F'[-}]' '{print $2}' 10.1.0.0/16 # 修改 yaml 文件，将 CALICO_IPV4POOL_CIDR 修改为获取的 Pod 网络 $ sed -i \ -e '/CALICO_IPV4POOL_CIDR/ s/#\ //' \ -e '/192.168.0.0\/16/ s/#\ //' \ -e "/192.168.0.0\/16/ s/192.168.0.0\/16/10.1.0.0\/16/" \ /root/release-v3.28.2/manifests/calico.yaml # 启动 calico $ kubectl apply -f /root/release-v3.28.2/manifests/calico.yaml # 查看 pod 是否正常运行 $ kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system calico-kube-controllers-658958974b-m6jn2 1/1 Running 0 29s kube-system calico-node-4c84x 1/1 Running 0 29s kube-system coredns-69cbfb9798-hlqvv 1/1 Running 0 5m5s5 如何切换版本# 进入克隆的 Kubernetes 源代码目录 $ cd ${GOPATH}/src/kubernetes/kubernetes # 查看所有版本分支 $ git ls-remote --tags origin # 将 Kubernetes 强制切换到需要的版本 $ git checkout -f v1.31.3 Previous HEAD position was 960a2f01931 Release commit for Kubernetes v1.29.11 HEAD is now at c83cbee114d Release commit for Kubernetes v1.31.3 # 执行编译命令，编译所有工具 $ KUBE_BUILD_PLATFORMS="$(go env GOHOSTOS)/$(go env GOHOSTARCH)" make all GOFLAGS=-v GOGCFLAGS="-N -l" # 测试新版本命令 $ kubeadm version kubeadm version: &version.Info{Major:"1", Minor:"31", GitVersion:"v1.31.3", GitCommit:"c83cbee114ddb732cdc06d3d1b62c9eb9220726f", GitTreeState:"clean", BuildDate:"2024-12-02T06:04:02Z", GoVersion:"go1.22.8", Compiler:"gc", Platform:"linux/amd64"} # 执行 etcd 安装脚本 $ ./hack/install-etcd.sh Downloading https://github.com/etcd-io/etcd/releases/download/v3.5.15/etcd-v3.5.15-linux-amd64.tar.gz succeed # 测试新版本命令 $ etcd --version etcd Version: 3.5.15 Git SHA: 9a5533382 Go Version: go1.21.12 Go OS/Arch: linux/amd64 # 必须删除 cni 插件，否则会导致 coredns 启动失败。详见 6（2） $ rm -rf /opt/cni # 后续按照第 4 章中的方法启动即可6 FAQ（1）/root/go/src/kubernetes/kubernetes/_output/local/.gimme/versions/go1.22.8.linux.amd64/pkg/tool/linux_amd64/link: mapping output file failed: no space left on device问题现象：问题原因：编译过程中需要向 /tmp 目录写入临时文件，但该目录空间不足解决方案：若 /tmp 为单独挂载的 tmpfs 文件系统。则将其卸载：# 查看 /tmp 是否挂载 $ df -Th /tmp Filesystem Type Size Used Avail Use% Mounted on tmpfs tmpfs 2.7G 66M 2.6G 3% /tmp # 卸载 /tmp $ umount -fl /tmp（2）切换分支后，coredns 启动失败问题现象：执行 kubectl describe pod -n kube-system coredns-*-* 命令，看到包含类似如下报错：问题原因：切换版本后，cni 插件不兼容，导致网络有问题解决方案：每次切换版本，都要及时删除 cni 插件：$ rm -rf /opt/cni附录 部署 Containerd# 下载 containerd 包 $ wget https://github.com/containerd/containerd/releases/download/v1.7.15/cri-containerd-cni-1.7.15-linux-amd64.tar.gz -P /root # 将下载的包解压到根目录中，压缩包自带目录结构 $ tar -xvf /root/cri-containerd-cni-1.7.15-linux-amd64.tar.gz -C / # 创建配置文件目录 $ mkdir /etc/containerd # 生成配置文件 $ containerd config default > /etc/containerd/config.toml # 配置 systemdcgroup 驱动程序 $ sed -i '/SystemdCgroup/ s/false/true/' /etc/containerd/config.toml # 更新runc，因为cri-containerd-cni-1.6.6-linux-amd64.tar.gz的runc二进制文件有问题，最后说明。这一步很重要 ✰ ✰ ✰ # wget https://github.com/opencontainers/runc/releases/download/v1.1.3/runc.amd64 # mv runc.amd64 /usr/local/sbin/runc # mv：是否覆盖"/usr/local/sbin/runc"？ y # chmod +x /usr/local/sbin/runc # 创建服务配置目录 $ mkdir -p /etc/systemd/system/containerd.service.d # 配置代理 $ cat > /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF [Service] Environment="HTTP_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="HTTPS_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="NO_PROXY=localhost,127.0.0.1" EOF # 重新加载配置 $ systemctl daemon-reload # 启动 containerd 服务并设置开机自启 $ systemctl start containerd && systemctl enable containerd Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /etc/systemd/system/containerd.service. # 查看 containerd 服务状态 $ systemctl status containerd ● containerd.service - containerd container runtime Loaded: loaded (/etc/systemd/system/containerd.service; enabled; preset: disabled) Active: active (running) since Mon 2024-12-02 08:54:44 CST; 19s ago Docs: https://containerd.io Main PID: 3129 (containerd) Tasks: 12 Memory: 10.6M () CGroup: /system.slice/containerd.service └─3129 /usr/local/bin/containerd ...... # 测试拉取镜像 $ ctr image pull docker.io/library/hello-world:latest docker.io/library/hello-world:latest: resolved |++++++++++++++++++++++++++++++++++++++| index-sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966: done |++++++++++++++++++++++++++++++++++++++| manifest-sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57: done |++++++++++++++++++++++++++++++++++++++| config-sha256:d2c94e258dcb3c5ac2798d32e1249e42ef01cba4841c2234249495f87264ac5a: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:c1ec31eb59444d78df06a974d155e597c894ab4cda84f08294145e845394988e: done |++++++++++++++++++++++++++++++++++++++| elapsed: 5.1 s total: 14.4 K (2.8 KiB/s) unpacking linux/amd64 sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966... done: 29.001739ms # 查看套接字文件，调用方法：unix:///run/containerd/containerd.sock $ ls -l /run/containerd/containerd.sock srw-rw---- 1 root root 0 Dec 2 09:15 /run/containerd/containerd.sock
基于 openEuler 22.03 LTS SP4 编译 docker 20.10.13
1 编译目标由于 openEuler 所有版本适配的 docker 版本为 18.09，版本比较低不能满足大部分使用场景。因此本文以基于openEuler 22.03 LTS SP4 操作系统编译 docker-ce-20.10.13 为例，演示在 openEuler 操作系统上编译高版本 docker 的操作流程2 环境准备2.1 网络环境由于编译 docker 所需的源代码资源都在外网，因此需要提前配置代理# 配置代理 PROXY_IP=192.168.230.1 PROXY_PORT=1080 export http_proxy=http://${PROXY_IP}:${PROXY_PORT} export https_proxy=http://${PROXY_IP}:${PROXY_PORT} export ALL_PROXY=http://${PROXY_IP}:${PROXY_PORT} export all_proxy=socks://${PROXY_IP}:${PROXY_PORT} # 测试代理 $ curl www.google.com2.2 编译工具安装必要的编译工具$ yum install -y rpm-build rpmdevtools gcc gcc-c++ make golang2.3 编译资源软件包名下载地址docker-ce-20.10.10-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-20.10.10-3.el8.src.rpmdocker-ce-cli-20.10.13-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-cli-20.10.13-3.el8.src.rpmdocker-ce-rootless-extras-20.10.13-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-rootless-extras-20.10.13-3.el8.src.rpmcontainerd.io-1.4.3-3.2.src.rpmhttps://repo.openeuler.openatom.cn/openEuler-preview/sw_arch/openEuler-22.03-LTS/sources/Packages/containerd.io-1.4.3-3.2.src.rpmdocker-scan-plugin-0.12.0-3.el8.src.rpmhttps://download.docker.com/linux/centos/8/source/stable/Packages/docker-scan-plugin-0.12.0-3.el8.src.rpm3 编译流程3.1 编译 docker-ce3.1.1 编译# 定义 GOPATH 路径 $ export GOPATH=/go # 设置不使用 Go Modules 功能 $ export GO111MODULE=off # 从 docker 官方仓库下载 docker-ce-20.10.10-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-20.10.10-3.el8.src.rpm -P /root -2024-11-09 12:39:03-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-20.10.10-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 11328477 (11M) [binary/octet-stream] Saving to: ‘/root/docker-ce-20.10.10-3.el8.src.rpm’ docker-ce-20.10.10-3.el8. 100%[==================>] 10.80M 1.67MB/s in 7.5s 2024-11-09 12:39:12 (1.44 MB/s) - ‘/root/docker-ce-20.10.10-3.el8.src.rpm’ saved [11328477/11328477] # 安装 docker-ce-20.10.10-3.el8.src.rpm源码包 $ rpm -ivh /root/docker-ce-20.10.10-3.el8.src.rpm warning: /root/docker-ce-20.10.10-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-ce-3:20.10.10-3.el8 ################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _version 20.10.13' \ -e '1i %define _release 3' \ -e '1i %define _origversion %{_version}' \ -e '1i \ ' \ docker-ce.spec # 安装编译包依赖 $ yum builddep -y docker-ce.spec # 开始编译 $ rpmbuild -ba docker-ce.spec3.1.2 FAQ（1）no required module provides package github.com/docker/libnetwork/cmd/proxy: go.mod file not found in current directory or any parent directory; see 'go help modules' 报错信息：报错原因：参考文献：报错no required module provides package github.comxx的解决方案-CSDN博客Go Modules 是在 Go 1.11 版本中引入的。此时从 git 上下载的依赖库不再保存在 GOPATH 中，而是存到当前项目中，并使用 go.mod 文件跟踪依赖库和其版本。GO111MODULE 这个环境变量也是此时引入的，作为控制是否开启 Go Modules 的开关，Go Modules 和 GOPATH 是两个对立的依赖存储和搜索方式解决方案：从 Go 1.16 开始，默认行为是 GO111MODULE=on，这意味着如果您想继续使用旧 GOPATH 方式，则必须强制 Go 不使用 Go Modules 功能：$ export GO111MODULE=off（2）error: missing GOPATH; please see https://golang.org/doc/code.html#GOPATH alternatively, set AUTO_GOPATH=1 报错信息：报错原因：GOPATH 变量未定义$ echo $GOPATH 解决方案：指定 GOPATH 变量$ export GOPATH=/go3.2 编译 docker-ce-cli3.2.1 编译# 定义 GOPATH 路径 $ export GOPATH=/go # 添加 PATH 变量 $ export PATH=${PATH}:${GOPATH}/bin # 设置不使用 Go Modules 功能 $ export GO111MODULE=off # 从 docker 官方仓库下载 docker-ce-cli-20.10.13-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-cli-20.10.13-3.el8.src.rpm -P /root --2024-11-09 17:26:50-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-cli-20.10.13-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 7688788 (7.3M) [binary/octet-stream] Saving to: ‘/root/docker-ce-cli-20.10.13-3.el8.src.rpm’ docker-ce-cli-20.10.13-3. 100%[==================>] 7.33M 1.64MB/s in 4.5s 2024-11-09 17:26:56 (1.64 MB/s) - ‘/root/docker-ce-cli-20.10.13-3.el8.src.rpm’ saved [7688788/7688788] # 安装 docker-ce-cli-20.10.13-3.el8.src.rpm 源码包 $ rpm -ivh /root/docker-ce-cli-20.10.13-3.el8.src.rpm warning: /root/docker-ce-cli-20.10.13-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-ce-cli-1:20.10.13-3.el8 ################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _version 20.10.13' \ -e '1i %define _release 3' \ -e '1i %define _origversion %{_version}' \ -e '1i \ ' \ docker-ce-cli.spec # 安装编译包依赖 $ yum builddep -y docker-ce-cli.spec # 开始编译 $ rpmbuild -ba docker-ce-cli.spec3.2.2 FAQ（1）cannot find package "github.com/docker/cli/cmd/docker" in any of报错信息：报错原因：GOPATH 变量未定义$ echo $GOPATH 解决方案：指定 GOPATH 变量$ export GOPATH=/go（2）go: cannot find main module, but found vendor.conf in /go/src/github.com/docker/cli报错信息：报错原因：参考文献：报错no required module provides package github.comxx的解决方案-CSDN博客Go Modules 是在 Go 1.11 版本中引入的。此时从 git 上下载的依赖库不再保存在 GOPATH 中，而是存到当前项目中，并使用 go.mod 文件跟踪依赖库和其版本。GO111MODULE 这个环境变量也是此时引入的，作为控制是否开启 Go Modules 的开关，Go Modules 和 GOPATH 是两个对立的依赖存储和搜索方式解决方案：从 Go 1.16 开始，默认行为是 GO111MODULE=on，这意味着如果您想继续使用旧 GOPATH 方式，则必须强制 Go 不使用 Go Modules 功能：$ export GO111MODULE=off（3）./man/md2man-all.sh: line 21: go-md2man: command not found报错信息：报错原因：未找到 go-md2man 命令，实际此时该命令已经编译成功，位于 /go/bin 目录中$ ls -l /go/bin/ total 2604 -rwxr-xr-x 1 root root 2666053 Nov 9 17:39 go-md2man解决方案：将 /go/bin 添加 PATH 变量# 将 /go/bin 添加 PATH 变量 $ export PATH=${PATH}:${GOPATH}/bin # 查询是否能找到 go-md2man 命令 $ which go-md2man /go/bin/go-md2man3.3 编译 docker-ce-rootless-extras# 从 docker 官方仓库下载 docker-ce-rootless-extras-20.10.13-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm -P /root --2024-11-09 17:52:50-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 11211542 (11M) [binary/octet-stream] Saving to: ‘/root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm’ docker-ce-rootless-extras 100%[==================>] 10.69M 2.57MB/s in 4.2s 2024-11-09 17:52:55 (2.57 MB/s) - ‘/root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm’ saved [11211542/11211542] # 安装 docker-ce-rootless-extras-20.10.13-3.el8.src.rpm 源码包 $ rpm -ivh /root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm warning: /root/docker-ce-rootless-extras-20.10.13-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-ce-rootless-extras-0:20.10################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _version 20.10.13' \ -e '1i %define _release 3' \ -e '1i \ ' \ docker-ce-rootless-extras.spec # 安装编译包依赖 $ yum builddep -y docker-ce-rootless-extras.spec # 开始编译 $ rpmbuild -ba docker-ce-rootless-extras.spec3.4 编译 containerd.io3.4.1 编译（1）环境准备# 定义 GOPATH 路径 $ export GOPATH=/root/go（2）部署 containerd 源码# 创建存放 containerd 的源码目录 $ mkdir -p $GOPATH/src/github.com/containerd # 进入存放 containerd 的源码目录 $ cd $GOPATH/src/github.com/containerd # 克隆 containerd 源码 $ git clone https://github.com/containerd/containerd.git Cloning into 'containerd'... remote: Enumerating objects: 148247, done. remote: Counting objects: 100% (19157/19157), done. remote: Compressing objects: 100% (1209/1209), done. remote: Total 148247 (delta 18390), reused 18188 (delta 17926), pack-reused 129090 (from 1) Receiving objects: 100% (148247/148247), 113.09 MiB | 2.27 MiB/s, done. Resolving deltas: 100% (96229/96229), done. # 进入克隆的 containerd 源码目录 $ cd $GOPATH/src/github.com/containerd/containerd # 切换分支，因为高版本分支需要较高的 go 版本支持 $ git checkout v1.5.18 # 确认分支是否正确 $ git branch * (HEAD detached at v1.5.18) main（3）部署 runc 源码# 创建存放 runc 的源码目录 $ mkdir -p $GOPATH/src/github.com/opencontainers # 进入存放 runc 的源码目录 $ cd $GOPATH/src/github.com/opencontainers # 克隆 runc 源码 $ git clone https://github.com/opencontainers/runc.git Cloning into 'runc'... remote: Enumerating objects: 44540, done. remote: Counting objects: 100% (194/194), done. remote: Compressing objects: 100% (138/138), done. remote: Total 44540 (delta 80), reused 126 (delta 49), pack-reused 44346 (from 1) Receiving objects: 100% (44540/44540), 22.01 MiB | 1.52 MiB/s, done. Resolving deltas: 100% (29266/29266), done. # 进入克隆的 runc 源码目录 $ cd $GOPATH/src/github.com/opencontainers/runc # 切换分支，因为高版本分支需要较高的 go 版本支持 $ git checkout v1.1.12 # 确认分支是否正确 $ git branch * (HEAD detached at v1.1.12) main（4）部署 go-md2man 工具命令# 安装 go-md2man 工具命令 $ go install github.com/cpuguy83/go-md2man/v2@latest # 查看命令是否安装成功 $ ls -l ${GOPATH}/bin total 2624 -rwxr-xr-x 1 root root 2685640 Nov 9 19:59 go-md2man # 将命令路径添加到 PATH $ export PATH=${PATH}:${GOPATH}/bin # 查询是否能找到 go-md2man 命令 $ which go-md2man /root/go/bin/go-md2man（5）编译 containerd.io# 从 OEPKGS 仓库下载 containerd.io-1.4.3-3.2.src.rpm 源码包 $ wget https://repo.openeuler.openatom.cn/openEuler-preview/sw_arch/openEuler-22.03-LTS/sources/Packages/containerd.io-1.4.3-3.2.src.rpm -P /root --2024-11-09 19:32:48-- https://repo.openeuler.openatom.cn/openEuler-preview/sw_arch/openEuler-22.03-LTS/sources/Packages/containerd.io-1.4.3-3.2.src.rpm Resolving repo.openeuler.openatom.cn (repo.openeuler.openatom.cn)... 124.70.105.51 Connecting to repo.openeuler.openatom.cn (repo.openeuler.openatom.cn)|124.70.105.51|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 15017 (15K) [application/x-redhat-package-manager] Saving to: ‘/root/containerd.io-1.4.3-3.2.src.rpm’ containerd.io-1.4.3-3.2.s 100%[==================>] 14.67K 45.6KB/s in 0.3s 2024-11-09 19:32:48 (45.6 KB/s) - ‘/root/containerd.io-1.4.3-3.2.src.rpm’ saved [15017/15017] # 安装 containerd.io-1.4.3-3.2.src.rpm 源码包 $ rpm -ivh /root/containerd.io-1.4.3-3.2.src.rpm Updating / installing... 1:containerd.io-1.4.3-3.2 ################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i '/^rm -rf %{_topdir}\/BUILD\// s/\/$//' containerd.spec # 定义 spec 文件中需要的环境变量 $ export RPM_VERSION=1.4.3 $ export RPM_RELEASE_VERSION=3.2 # 安装编译包依赖 $ yum builddep -y containerd.spec # 开始编译 $ rpmbuild -ba containerd.spec3.4.2 FAQ（1）RPM: error: line 46: Empty tag: Version报错信息：报错原因：containerd.spec 文件中第 46 行和第 47 行为定义 rpm 包的版本信息，其变量的值来自于环境变量 RPM_VERSION 和 RPM_RELEASE_VERSION，但是这两个环境变量未定义Version: %{getenv:RPM_VERSION} Release: %{getenv:RPM_RELEASE_VERSION}解决方案：在命令行中定义环境变量：RPM_VERSION 和 RPM_RELEASE_VERSION$ export RPM_VERSION=1.4.3 $ export RPM_RELEASE_VERSION=3.2（2）is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt报错信息：报错原因：go.mod 文件和 vendor/modules.txt 文件之间存在不一致解决方案：重新拉取源代码，确认go.mod 文件和 vendor/modules.txt 文件是否一致3.5 编译 docker-scan-plugin# 从 docker 官方仓库下载 docker-scan-plugin-0.12.0-3.el8.src.rpm 源码包 $ wget https://download.docker.com/linux/centos/8/source/stable/Packages/docker-scan-plugin-0.12.0-3.el8.src.rpm -P /root --2024-11-09 20:38:29-- https://download.docker.com/linux/centos/8/source/stable/Packages/docker-scan-plugin-0.12.0-3.el8.src.rpm Connecting to 192.168.230.1:1080... connected. Proxy request sent, awaiting response... 200 OK Length: 104035 (102K) [binary/octet-stream] Saving to: ‘/root/docker-scan-plugin-0.12.0-3.el8.src.rpm’ docker-scan-plugin-0.12.0 100%[==================>] 101.60K 278KB/s in 0.4s 2024-11-09 20:38:33 (278 KB/s) - ‘/root/docker-scan-plugin-0.12.0-3.el8.src.rpm’ saved [104035/104035] # 安装 docker-scan-plugin-0.12.0-3.el8.src.rpm 源码包 $ rpm -ivh /root/docker-scan-plugin-0.12.0-3.el8.src.rpm warning: /root/docker-scan-plugin-0.12.0-3.el8.src.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Updating / installing... 1:docker-scan-plugin-0:0.12.0-3.el8################################# [100%] # 进入 spec 文件目录 $ cd /root/rpmbuild/SPECS # 修改 spec 文件 $ sed -i \ -e '1i %define _scan_rpm_version 0.12.0' \ -e '1i %define _release 3' \ -e '1i %define _scan_version v%{_scan_rpm_version}' \ -e '1i \ ' \ docker-scan-plugin.spec # 安装编译包依赖 $ yum builddep -y docker-scan-plugin.spec # 开始编译 $ rpmbuild -ba docker-scan-plugin.spec4 安装测试（1）安装# 进入存放构建完成的 rpm 包目录 $ cd /root/rpmbuild/RPMS/x86_64/ # 查看编译完成的 rpm 包 $ ls -l total 91636 -rw-r--r-- 1 root root 31520637 Nov 9 20:32 containerd.io-1.4.3-3.2.x86_64.rpm -rw-r--r-- 1 root root 22738649 Nov 9 17:10 docker-ce-20.10.13-3.x86_64.rpm -rw-r--r-- 1 root root 30831385 Nov 9 17:46 docker-ce-cli-20.10.13-3.x86_64.rpm -rw-r--r-- 1 root root 4890517 Nov 9 19:20 docker-ce-rootless-extras-20.10.13-3.x86_64.rpm -rw-r--r-- 1 root root 3842797 Nov 9 20:44 docker-scan-plugin-0.12.0-3.x86_64.rpm # 执行本地安装 $ yum localinstall *.rpm（2）测试# 配置加速地址 $ cat >> /etc/docker/daemon.json <<EOF { "registry-mirrors": [ "https://367e3d3a84aa407eb200df7aab688eaf.mirror.swr.myhuaweicloud.com" ] } EOF # 启动 docker 并设置开机自启 $ systemctl start docker && systemctl enable docker Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service. # 查看 docker 基本信息 $ docker info Client: Context: default Debug Mode: false Plugins: app: Docker App (Docker Inc., v0.9.1-beta3) buildx: Docker Buildx (Docker Inc., v0.8.0-docker) scan: Docker Scan (Docker Inc., v0.12.0) Server: Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 20.10.13 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc Default Runtime: runc Init Binary: docker-init containerd version: runc version: v1.1.12-0-g51d5e946 init version: de40ad0 Kernel Version: 5.10.0-216.0.0.115.oe2203sp4.x86_64 Operating System: openEuler 22.03 (LTS-SP4) OSType: linux Architecture: x86_64 CPUs: 8 Total Memory: 7.228GiB Name: localhost.localdomain ID: S6QG:FGLU:ZJC2:2N2Q:6SZS:HDTN:MDBY:CACI:DQ7Q:SX3B:XJ34:MFNO Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false # 拉取镜像 $ docker pull openeuler/openeuler:22.03-lts-sp4 22.03-lts-sp4: Pulling from openeuler/openeuler 6550e36f5825: Pull complete 12f045674288: Pull complete Digest: sha256:7b3947d10e1f9459ffae6303349f9f7dba79a1eb992adaa10172df6cbdac2b4e Status: Downloaded newer image for openeuler/openeuler:22.03-lts-sp4 docker.io/openeuler/openeuler:22.03-lts-sp4 # 创建容器 $ docker run -d --name test01 openeuler/openeuler:22.03-lts-sp4 /bin/bash -c "sleep 3600" cca749590ba66bdd6812bba5e83c17d5be217772933cb3c725aa831883c93b9a
基于 openEuler 操作系统使用 Sealos 构建 Kubernetes 高可用集群
{card-default label="前情提要" width="100%"}本文篇幅较长，您可以耐心阅读，也可以从右侧目录中选择需要查看的部分{/card-default}1 前言（1）本文主要包含以下几个方面的内容：使用 Sealos 工具构建 Kubernetes 高可用集群（3 master，1 node）使用 Helm 安装 Ingress-nginx，并使用 Service 的 NodePort 模式向集群外部暴露端口部署 Prometheus 监控工具和 Grafana 图形化展示工具，使用 Ingress-nginx 作入口访问代理部署过程常见的错误及解决方案（2）本文使用机器详情主机名称身份IP 地址操作系统版本Linux 内核版本m0master192.168.255.100openEuler 22.03 (LTS-SP2)5.10.0-153.12.0.92.oe2203sp2.x86_64m1master192.168.255.101openEuler 22.03 (LTS-SP2)5.10.0-153.12.0.92.oe2203sp2.x86_64m2master192.168.255.102openEuler 22.03 (LTS-SP2)5.10.0-153.12.0.92.oe2203sp2.x86_64n1node192.168.255.103openEuler 22.03 (LTS-SP2)5.10.0-153.12.0.92.oe2203sp2.x86_64（3）组件版本及安装方式Kubernetes、Helm、Calico 均使用当前最新版本组件名称版本号安装方式软件来源Kubernetes1.28.3Sealos + 镜像labring/kubernetes - Docker ImageHelm3.12.3Sealos + 镜像labring/helm - Docker ImageCalico3.26.1Sealos + 镜像labring/calico - Docker ImageIngress-nginx4.8.3Helm + Chart 包ingress-nginx 4.8.3 · kubernetes/ingress-nginx (artifacthub.io)Prometheus + Grafana0.13kubectlGitHub - prometheus-operator/kube-prometheus at release-0.13（4）注意事项请确保机器可以访问谷歌镜像仓库、红帽镜像仓库及 Github，需要下载镜像及源代码主机之间最好能够相互免密登录主机之间保持时间同步主机名称唯一，不能相同不要自己装 Docker2 Kubernetes 集群构建2.1 下载 sealos 工具注意：此步骤需要在所有节点运行# 获取 sealos 工具的所有可用版本号 [root@m0 ~]# curl --silent "https://api.github.com/repos/labring/sealos/releases" | jq -r '.[].tag_name' v5.0.0-alpha2 v4.3.7-rc1 v4.3.6 v4.4.0-beta2 v4.4.0-beta1 v4.3.5 v4.3.4 v4.4.0-alpha3 v4.4.0-alpha1 v4.3.3 v4.3.2 ...... # 设置 VERSION 环境变量，此处我设置为 v4.3.6，即安装 4.3.6 版本 [root@m0 ~]# VERSION=v4.3.6 && echo $VERSION v4.3.6 # 下载 sealos 工具 [root@m0 ~]# wget https://github.com/labring/sealos/releases/download/${VERSION}/sealos_${VERSION#v}_linux_amd64.tar.gz 正在保存至: “sealos_4.3.6_linux_amd64.tar.gz” sealos_4.3.6_linux_amd64.tar.gz 100%[===================================>] 60.05M 9.58MB/s 用时 7.8s 2023-10-30 15:24:15 (7.69 MB/s) - 已保存 “sealos_4.3.6_linux_amd64.tar.gz” [62963874/62963874]) # 解压 sealos 工具，加可执行权限，并将其移动到 /usr/local/bin/ 目录下 [root@m0 ~]# tar -zxvf sealos_4.3.6_linux_amd64.tar.gz sealos && chmod +x sealos && mv sealos /usr/local/bin # 查看 sealos 工具是否安装成功 [root@m0 ~]# sealos version SealosVersion: buildDate: "2023-10-20T14:15:00Z" compiler: gc gitCommit: a2719848 gitVersion: 4.3.6 goVersion: go1.20.10 platform: linux/amd642.2 sealos 相关命令（1）sealos run 构建集群# 构建 Kubernetes 高可用集群 $ sealos run IMAGE --masters IP1,IP2,IP3... --nodes IP1,IP2,IP3... -p SSH-PASSWORD 参数说明： IMAGE：需要安装的 Kubernetes 及组件的镜像 --masters：指定 Kubernetes master 节点的 IP 地址 --nodes：指定 Kubernetes node 节点的 IP 地址 -p SSH-PASSWORD：指定 SSH 远程登录的密码 例程： $ sealos run labring/kubernetes:v1.25.0 labring/helm:v3.8.2 labring/calico:v3.24.1 \ --masters 192.168.64.2,192.168.64.22,192.168.64.20 \ --nodes 192.168.64.21,192.168.64.19 \ -p 123456（2）sealos run 安装应用# 安装各种应用 $ sealos run IMAGE 参数说明： IMAGE：要安装的应用的镜像 例程： $ sealos run labring/helm:v3.8.2（3） sealos add 增加节点# 增加 master 节点 $ sealos add --masters 192.168.1.1,192.168.1.2 # 增加 node 节点 $ sealos add --nodes 192.168.1.3,192.168.1.4（4） sealos delete 删除节点# 删除 master 节点 $ sealos delete --masters 192.168.1.1,192.168.1.2 # 删除 node 节点 $ sealos delete --nodes 192.168.1.3,192.168.1.4（5）sealos reset 清理集群# 清理 Kubernetes 集群 $ sealos reset（6）sealos status 查看集群# 查看 Kubernetes 集群运行状态 $ sealos status（7）其他命令# 同 docker 命令的用法，不再赘述 $ sealos pull $ sealos images $ sealos rmi $ sealos ps2.3 使用 sealos 构建集群再次申明安装注意事项（参考官方说明）：每个集群节点应该有不同的主机名。 主机名不要带下划线所有节点的时间同步在 Kubernetes 集群的第一个节点上运行sealos run命令，目前集群外的节点不支持集群安装建议使用干净的操作系统来创建集群。不要自己装 Docker支持大多数 Linux 发行版，例如：Ubuntu CentOS Rocky linux支持 DockerHub 中支持的 Kubernetes 版本支持使用 containerd 作为容器运行时在公有云上请使用私有 IP注意：此步骤只在第一个 master 节点上执行（1）执行以下命令构建集群[root@m0 ~]# sealos run labring/kubernetes:v1.28.3 labring/helm:v3.12.3 labring/calico:v3.26.1 \ --masters 192.168.255.100,192.168.255.101,192.168.255.102 \ --nodes 192.168.255.103 \ -p 123456（2）执行上述命令后，不需要额外操作，一直等待出现以下界面，表示构建完成2023-10-30T15:49:36 info succeeded in creating a new cluster, enjoy it! 2023-10-30T15:49:36 info ___ ___ ___ ___ ___ ___ /\ \ /\ \ /\ \ /\__\ /\ \ /\ \ /::\ \ /::\ \ /::\ \ /:/ / /::\ \ /::\ \ /:/\ \ \ /:/\:\ \ /:/\:\ \ /:/ / /:/\:\ \ /:/\ \ \ _\:\~\ \ \ /::\~\:\ \ /::\~\:\ \ /:/ / /:/ \:\ \ _\:\~\ \ \ /\ \:\ \ \__\ /:/\:\ \:\__\ /:/\:\ \:\__\ /:/__/ /:/__/ \:\__\ /\ \:\ \ \__\ \:\ \:\ \/__/ \:\~\:\ \/__/ \/__\:\/:/ / \:\ \ \:\ \ /:/ / \:\ \:\ \/__/ \:\ \:\__\ \:\ \:\__\ \::/ / \:\ \ \:\ /:/ / \:\ \:\__\ \:\/:/ / \:\ \/__/ /:/ / \:\ \ \:\/:/ / \:\/:/ / \::/ / \:\__\ /:/ / \:\__\ \::/ / \::/ / \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ Website: https://www.sealos.io/ Address: github.com/labring/sealos Version: 4.3.6-a2719848（3）查看 Kubernetes 集群运行状态[root@m0 ~]# sealos status ...... Systemd Service Status Logger: journalctl -xeu SERVICE-NAME Error: <nil> Init System List: Name: kubelet Status: Enable && Active Name: containerd Status: Enable && Active Name: cri-docker Status: Disable && NotActive Name: docker Status: Disable && NotActive Name: registry Status: Enable && Active Name: image-cri-shim Status: Enable && Active Cluster Node Status ReadyNode: 4/4 Cluster Pod Status Namespace: calico-apiserver RunningPod: 2/2 Namespace: calico-system RunningPod: 11/11 Namespace: default RunningPod: 0/0 Namespace: kube-node-lease RunningPod: 0/0 Namespace: kube-public RunningPod: 0/0 Namespace: kube-system RunningPod: 19/19 Namespace: tigera-operator RunningPod: 1/1 Cluster Service Status Namespace: calico-apiserver HealthService: 1/1 UnhealthServiceList: Namespace: calico-system HealthService: 2/2 UnhealthServiceList: Namespace: default HealthService: 1/1 UnhealthServiceList: Namespace: kube-node-lease HealthService: 0/0 UnhealthServiceList: Namespace: kube-public HealthService: 0/0 UnhealthServiceList: Namespace: kube-system HealthService: 1/1 UnhealthServiceList: Namespace: tigera-operator HealthService: 0/0 UnhealthServiceList: Error: failed to run checker: pods "kube-apiserver-n1" not found（4）查看主要组件 Pod 运行情况[root@m0 ~]# kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE calico-apiserver calico-apiserver-5c7799c9d7-bclsw 1/1 Running 0 6m31s calico-apiserver calico-apiserver-5c7799c9d7-fkqjx 1/1 Running 0 6m31s calico-system calico-kube-controllers-65f68c6768-8vhnp 1/1 Running 0 7m5s calico-system calico-node-6dgtc 1/1 Running 0 7m5s calico-system calico-node-clbn7 1/1 Running 0 7m5s calico-system calico-node-gf8kh 1/1 Running 0 7m5s calico-system calico-node-lqzlb 1/1 Running 0 7m5s calico-system calico-typha-b98b4d5f8-dx649 1/1 Running 0 6m57s calico-system calico-typha-b98b4d5f8-hlclk 1/1 Running 0 7m5s calico-system csi-node-driver-29z2d 2/2 Running 0 7m5s calico-system csi-node-driver-c7wrb 2/2 Running 0 7m5s calico-system csi-node-driver-f79sh 2/2 Running 0 7m5s calico-system csi-node-driver-rlrw4 2/2 Running 0 7m5s kube-system coredns-5dd5756b68-7r7mw 1/1 Running 0 11m kube-system coredns-5dd5756b68-x2g2x 1/1 Running 0 11m kube-system etcd-m0 1/1 Running 0 11m kube-system etcd-m1 1/1 Running 0 9m13s kube-system etcd-m2 1/1 Running 0 7m27s kube-system kube-apiserver-m0 1/1 Running 0 11m kube-system kube-apiserver-m1 1/1 Running 0 9m9s kube-system kube-apiserver-m2 1/1 Running 0 7m17s kube-system kube-controller-manager-m0 1/1 Running 0 11m kube-system kube-controller-manager-m1 1/1 Running 0 9m6s kube-system kube-controller-manager-m2 1/1 Running 0 7m27s kube-system kube-proxy-9nsl5 1/1 Running 0 9m18s kube-system kube-proxy-hdlbn 1/1 Running 0 7m14s kube-system kube-proxy-ptq8n 1/1 Running 0 11m kube-system kube-proxy-xhphx 1/1 Running 0 7m28s kube-system kube-scheduler-m0 1/1 Running 0 11m kube-system kube-scheduler-m1 1/1 Running 0 9m12s kube-system kube-scheduler-m2 1/1 Running 0 7m23s kube-system kube-sealos-lvscare-n1 1/1 Running 0 6m57s tigera-operator tigera-operator-94d7f7696-zwzh5 1/1 Running 0 7m10s所有 Pod 均为 Running 状态，至此 Kubernetes 集群构建完成3 安装 Ingress-nginx（1）添加 Helm 仓库[root@m0 ~]# helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx "ingress-nginx" has been added to your repositories（2）下载 Ingress-nginx 的 chart 包，并解压[root@m0 ~]# helm fetch ingress-nginx/ingress-nginx --version 4.8.3 [root@m0 ~]# ls ingress-nginx-4.8.3.tgz [root@m0 ~]# tar -zxvf ingress-nginx-4.8.3.tgz（3）修改 values.yaml 文件因为默认的暴露方式为 LoadBalancer，需要对接云平台，因此需要将 values.yaml 中的 LoadBalance 更改为 NodePort，并进行暴露端口的配置[root@m0 ~]# cd ingress-nginx [root@m0 ingress-nginx]# vim values.yaml type: NodePort ## type: NodePort ## nodePorts: ## http: 32080 ## https: 32443 ## tcp: ## 8080: 32808 nodePorts: http: "32080" https: "32443"（4）部署 Ingress-nginx# 创建 ingress-nginx 名字空间 [root@m0 ingress-nginx]# kubectl create namespace ingress-nginx namespace/ingress-nginx created # 安装 ingress-nginx，注意命令末尾的 . 不能省略，表示当前目录 [root@m0 ingress-nginx]# helm install -n ingress-nginx ingress-nginx -f values.yaml .（5）等待出现以下提示，表示安装完成，还需进一步确认 pod 运行状态NAME: ingress-nginx LAST DEPLOYED: Mon Oct 30 18:08:16 2023 NAMESPACE: ingress-nginx STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: The ingress-nginx controller has been installed. Get the application URL by running these commands: export HTTP_NODE_PORT=32080 export HTTPS_NODE_PORT=32443 export NODE_IP=$(kubectl --namespace ingress-nginx get nodes -o jsonpath="{.items[0].status.addresses[1].address}") echo "Visit http://$NODE_IP:$HTTP_NODE_PORT to access your application via HTTP." echo "Visit https://$NODE_IP:$HTTPS_NODE_PORT to access your application via HTTPS." An example Ingress that makes use of the controller: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example namespace: foo spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - pathType: Prefix backend: service: name: exampleService port: number: 80 path: / # This section is only required if TLS is to be enabled for the Ingress tls: - hosts: - www.example.com secretName: example-tls If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided: apiVersion: v1 kind: Secret metadata: name: example-tls namespace: foo data: tls.crt: <base64 encoded cert> tls.key: <base64 encoded key> type: kubernetes.io/tls（6）确认 pod 的运行状态[root@m0 ingress-nginx]# kubectl get pod -n ingress-nginx NAME READY STATUS RESTARTS AGE ingress-nginx-controller-798796947c-tbp2m 1/1 Running 0 6m18sPod 的状态为 Running 表示安装全部成功（7）查看暴露的端口[root@m0 ingress-nginx]# kubectl get svc -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-controller NodePort 10.96.0.134 <none> 80:32080/TCP,443:32443/TCP 9m46s ingress-nginx-controller-admission ClusterIP 10.96.2.66 <none> 443/TCP 9m46s已对集群外暴露 32080 和 32443 端口，分别作为 HTTP 和 HTTPS 的端口号（8）访问测试在 Windows 浏览器中输入 http://Node_IP:32080，例如 http://192.168.255.100:32080 进行访问测试出现此界面表示安装配置成功，即能够开始使用 Ingress-nginx 了说明：在访问测试中，之所以出现 404 报错，是因为没有指定后端 Service，而是使用了默认后端，此为正常现象4 安装 Prometheus4.1 安装 Prometheus（1）从 Github 克隆源代码[root@m0 ~]# git clone https://github.com/prometheus-operator/kube-prometheus.git 正克隆到 'kube-prometheus'... remote: Enumerating objects: 18736, done. remote: Counting objects: 100% (5373/5373), done. remote: Compressing objects: 100% (332/332), done. remote: Total 18736 (delta 5194), reused 5060 (delta 5036), pack-reused 13363 接收对象中: 100% (18736/18736), 9.72 MiB | 4.60 MiB/s, 完成. 处理 delta 中: 100% (12619/12619), 完成. [root@m0 ~]# ls kube-prometheus（2）创建名字空间和 CDRs# 进入项目目录 [root@m0 ~]# cd kube-prometheus/ # 创建 monitoring 名字空间 [root@m0 kube-prometheus]# kubectl apply --server-side -f manifests/setup ...... namespace/monitoring serverside-applied # 创建 CRDs（Custom Resource Definition，自定义资源） [root@m0 kube-prometheus]# kubectl wait \ --for condition=Established \ --all CustomResourceDefinition \ --namespace=monitoring # 查看是否生效 [root@m0 kube-prometheus]# kubectl get namespace NAME STATUS AGE monitoring Active 109s（3）安装 prometheus[root@m0 kube-prometheus]# kubectl apply -f manifests/注意：Pod 之间存在互相调用关系，但是 Pod 创建有快慢，导致调用出现问题，因此需要根据命令返回的结果，可能需要多次执行该命令，直至所有返回结果均为 created 状态（4）查看 Pod 运行状态[root@m0 ~]# kubectl get pod -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-main-0 2/2 Running 0 3m1s alertmanager-main-1 2/2 Running 0 3m1s alertmanager-main-2 2/2 Running 0 3m1s blackbox-exporter-76b5c44577-crv2h 3/3 Running 0 5m5s grafana-748964b847-8d5c2 1/1 Running 0 5m3s kube-state-metrics-6c664d5dc8-xsqkm 3/3 Running 0 5m3s node-exporter-gxqct 2/2 Running 0 5m2s node-exporter-hf26f 2/2 Running 0 5m2s node-exporter-jvrk9 2/2 Running 0 5m2s node-exporter-qb8w7 2/2 Running 0 5m2s prometheus-adapter-7cc789bfcc-64wp8 1/1 Running 0 5m1s prometheus-adapter-7cc789bfcc-mr9zm 1/1 Running 0 5m1s prometheus-k8s-0 2/2 Running 0 3m prometheus-k8s-1 2/2 Running 0 3m prometheus-operator-6479b5dff9-6w9ft 2/2 Running 0 5m1s等待所有 Pod 全部为 Running 状态，则安装完成（5）查看相关的 Service[root@m0 ~]# kubectl get svc -n monitoring NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE alertmanager-main ClusterIP 10.96.3.53 <none> 9093/TCP,8080/TCP 3m37s alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 93s blackbox-exporter ClusterIP 10.96.1.22 <none> 9115/TCP,19115/TCP 3m37s grafana ClusterIP 10.96.0.151 <none> 3000/TCP 3m35s kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 3m35s node-exporter ClusterIP None <none> 9100/TCP 3m34s prometheus-adapter ClusterIP 10.96.2.118 <none> 443/TCP 3m33s prometheus-k8s ClusterIP 10.96.2.71 <none> 9090/TCP,8080/TCP 3m34s prometheus-operated ClusterIP None <none> 9090/TCP 92s prometheus-operator ClusterIP None <none> 8443/TCP 3m33s这里我们重点关注 grafana 和 prometheus-k8s 的 Service 名称和端口号，要在 ingress-nginx 中使用4.2 使用 Ingress 反向代理经过 4.1 的一顿操作，Prometheus 已经可以被正常访问了。然而，由于使用的 Service 的 ClusterIP 模式，因此只能在集群内部访问要想实现在集群外部访问，要么将 ClusterIP 模式更改为 NodePort 模式暴露端口，要么使用 Ingress 作反向代理访问，既然已经安装了 Ingress-nginx，那就用 Ingress 吧（1）创建名称为 prometheus-ingress.yaml 的资源清单[root@m0 ~]# vim prometheus-nginx.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: namespace: monitoring # 指定名字空间，需要和 Prometheus 所在的名字空间一致 name: prometheus # 随便起一个好记的名字吧 spec: ingressClassName: nginx # 重点，必须指定 ingress-ningx 类，使用此命令查询 kubectl get ingressclass rules: - host: grafana.k8s.xyz # 定义一个域名，访问此域名则访问 grafana http: paths: - path: / # 匹配所有路径 pathType: Prefix # 匹配规则为前缀匹配 backend: # 指定要代理的后端 service: # 后端为 Service name: grafana # 要访问的 Service 名称，必须和 kubectl get svc 查询到的一致 port: number: 3000 # 后端 Service 的端口号，必须和 kubectl get svc 查询到的一致 - host: prometheus.k8s.xyz http: paths: - path: / pathType: Prefix backend: service: name: prometheus-k8s port: number: 9090（2）将资源清单实例化[root@m0 ~]# kubectl apply -f prometheus-nginx.yaml ingress.networking.k8s.io/prometheus created（3）查看创建的 Ingress 对象[root@m0 ~]# kubectl get ingress -n monitoring NAME CLASS HOSTS ADDRESS PORTS AGE prometheus nginx grafana.k8s.xyz,prometheus.k8s.xyz 10.96.0.134 80 38s（4）查看反向代理规则[root@m0 ~]# kubectl get ingress -n monitoring prometheus ...... Rules: Host Path Backends ---- ---- -------- grafana.k8s.xyz / grafana:3000 (100.75.187.137:3000) prometheus.k8s.xyz / prometheus-k8s:9090 (100.94.130.69:9090,100.94.139.202:9090) ......若此处的后端（Backends）出现了 error 字样，则表示代理失败，原因及解决方案可查看第 5.2 节（5）访问测试注意：提前在 C:\Windows\System32\drivers\etc\hosts 配置好 DNS 解析规则关闭 Kubernetes 所有节点的防火墙并清空防火墙规则在 Windows 浏览器中输入 http://grafana.k8s.xyz:32080，即可进入 Grafana 界面在 Windows 浏览器中输入 http://prometheus.k8s.xyz:32080，即可进入 Grafana 界面4.3 配置路由器端口映射虽然在集群外使用 Windows 浏览器访问到 Prometheus 和 Grafana 了，但是每次输入域名还要输入端口号，这件事情一点都不优雅。另外，假如端口号忘记了，emm...，反正非常麻烦。要解决这一问题也很简单：将 NodePort 暴露的 Ingress 端口更改为 80 和 443 就好了。然而因为 Kubernetes 给 NodePort 分配默认端口号范围为 30000~32767 ，并且是不允许手动更改范围之外的端口号的，强行更改则需要先更改 Kubernetes 规则，此处不再详述，感兴趣的可以搜索教程另外也实在没必要折腾，因为折腾之后你会发现虽然能够在 Kubernetes 集群外访问，但还没有跳出局域网这个禁锢。即生产环境中不可能让我们直接访问后端服务器，都需要通过入口的路由器的公网网口，路由器端口映射（DNAT）完美解决了这个问题，这样就能实现真正的公网访问了（当然也可以使用外部方向代理）以下是具体操作流程：我使用的是 openWrt 软路由，wan 的 IP 地址为 192.168.230.230，lan 的 IP 地址为192.168.255.2，端口映射策略为：这个策略相当于以下防火墙规则：iptables -t nat -A PREROUTING -i eth0 -d 192.168.230.230 -p tcp --dport 80 -j DNAT --to-destination 192.168.255.101:32080此规则的具体含义为：任意来源 IP 只要访问公网网口的 80 端口，则将目标地址转换为内网 Kubernetes 集群的任意一台主机地址的 32080 端口也许你还有一个疑问，真实生产环境中，路由器的公网 IP 地址可能是动态 IP，经常发生变化，那我也不能总盯着 IP 地址来更新防火墙策略吧。解决这一个问题同样也很简单，只需将域名进行 DDNS（动态域名解析）配置，即可将域名精准解析到公网网口 IP，无论 IP 地址怎样变化此时，我们只需要访问 http://grafana.k8s.xyz 和 http://prometheus.k8s.xyz 即可访问 Grafana 和 Prometheus 了，终于不用输入那烦人的端口号了，是不是很优雅 😄注意：本文演示中，使用用 DNAT 策略将目标地址修改为集群某一个节点的 IP 地址和端口，这样做的缺点是若目标节点死亡，则访问会失败。实际上可以使用 Nginx 或 LVS 将流量负载到集群的多个节点上（因为 NodePort 模式会在集群所有节点上都绑定暴露的端口），既能防止单点故障又能降低单节点访问压力5 常见报错及处理方案5.1 访问失败或 502、504故障现象：使用浏览器访问集群内部服务时，访问失败，但并没有返回错误代码，如下图所示故障关键字：无法访问此网站排查思路：① 首先查看域名输入是否正确，是否是 Ingress 资源清单中 host 字段匹配的域名② 查看 DNS 是否正确配置，并且能否解析到正确的 IP 地址③ 不妨清理一下 Kubernetes 集群所有节点的防火墙规则吧疑问：在实验过程中发现，系统防火墙总是被创建了大量和 Calico 相关的自定义规则链和对应的规则，这些规则会阻挡集群外部的访问。当执行 iptables -F 命令清空防火墙规则后，并没有发现集群运行出现异常。等待一段时间后这些规则又会被创建，非常烦人，因此我直接使用了一个循环，每隔 5 秒清理一次防火墙规则5.2 Ingress 代理失败故障现象：在执行 kubectl describe ingress INGRESS_NAME 命令查看代理规则时，发现代理的后端 Service 出现 error，如图所示故障关键字：<error: endopints " " not fond>故障原因：虽然指定了后端 Service 和端口，但是指定的 Service 不能关联到提供服务的 Pod，这是因为 Ingress 对象所在的名字空间和提供服务的 Pod 及 Service 所在的名字空间不一致，出现了隔离 解决方案：在 Ingress 资源清单文件中指定和要关联的Service 和 Pod 相同的名字空间即可# 指定 .spec.metadata.namespace 字段 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: namespace: monitoring name: test spec: ingressClassName: nginx rules: - host: grafana.k8s.xyz.test http: paths: - path: / pathType: Prefix backend: service: name: grafana port: number: 3000 - host: prometheus.k8s.xyz.test http: paths: - path: / pathType: Prefix backend: service: name: prometheus-k8s port: number: 9090[root@m0 ~]# kubectl apply -f test.yaml ingress.networking.k8s.io/test created [root@m0 ~]# kubectl describe ingress -n monitoring test ...... Rules: Host Path Backends ---- ---- -------- grafana.k8s.xyz.test / grafana:3000 (100.75.187.149:3000) prometheus.k8s.xyz.test / prometheus-k8s:9090 (100.94.130.72:9090,100.94.139.204:9090) ......Ingress 反向代理正常，没有出现 error 字样5.3 Ingress 代理 404 报错故障现象：在配置好 Ingress 并确认代理的各项设置没问题后，访问时竟然出现 404 Not Found 报错排错思路：① 出现此报错说明已经能够访问 Ingress-nginx 了，先排除网络、防火墙方面的问题② 404 Not Found 错误代码含义为：请求资源无法被找到③ 既然确认了代理没问题，各项设置没有问题，那不妨查看 Ingress-nginx-controller 的日志怎么说吧为什么要查看 Ingress-nginx-controller 这个 Pod 的日志呢？Ingress-nginx 本身是一个 nginx 服务器。在安装 Ingress-nginx 控制器时，会部署一个名称为 Ingress-nginx-controller-xxxxx 的 Pod，里面运行了一个被魔改的 nginx当我们创建 Ingress 对象时，会把代理规则写入到这个 Pod 中的 nginx 配置文件中，此即 Ingress 对象和 Ingress-nginx 控制器的关系，查看这个 Pod 的日志即能够查看真实的访问流程及事件[root@m0 prometheus]# kubectl logs -n ingress-nginx ingress-nginx-controller-798796947c-tbp2m ...... W1031 06:06:44.699584 6 controller.go:331] ignoring ingress prometheus in monitoring based on annotation : ingress does not contain a valid IngressClass ......从日志中看到这样一段日志信息，其意为我们创建的 Ingress 对象没有包含可用的 IngressClass。那么问题来了，什么是 IngressClass？又该如何配置 IngressClass 呢？（1）什么是 IngressClass在安装 Ingress 控制器时，我们可能部署了多个不同类型的 Ingress Controller，或者部署了多个同一类型的 Ingress Controller（如部署多个 Ingress-nginx），为了区分不同的 Ingress Controller，会为每个 Ingress Controller 设定唯一的 Class，防止出错（2）如何配置 IngressClass① 首先执行如下命令，查看 IngressClassName[root@m0 ~]# kubectl get ingressclass NAME CONTROLLER PARAMETERS AGE nginx k8s.io/ingress-nginx <none> 20h② 在资源清单中添加 IngressClassName 字段# 在 .spec.ingressClassName 字段中指定 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: namespace: monitoring name: prometheus spec: ingressClassName: nginx rules: - host: grafana.k8s.xyz http: paths: - path: / pathType: Prefix backend: service: name: grafana port: number: 3000 - host: prometheus.k8s.xyz http: paths: - path: / pathType: Prefix backend: service: name: prometheus-k8s port: number: 9090问题完美解决，访问一切正常
1 背景Docker 官方网站的说明文档中，介绍了在各种 Linux 发行版系统上安装 Docker 的步骤及各种安装方法。例如，在 CentOS 上安装 Docker 可以参考：Install Docker Engine on CentOS | Docker Docs。众所周知，此网站在国内难以访问，当然也可以使用国内可用的 Yum 源。但总体的安装、配置步骤比较繁琐，尤其是在新旧版本切换时，常因为某些文件、目录未彻底清理，导致 Docker 启动失败。此脚本具有下功能：提供 docker-ce-17.03.0 版本和 docker-ce 最新稳定版的安装部署可以实现 dokcer-ce-17.03.0 版本和 docker-ce 最新稳定版的无缝切换安装，无需重启系统可以自动解决网桥与防火墙的连接问题，安装后无需重启系统若安装后存储驱动不是 overlay（overlay2），提供一键解决方案的选择内置初始化代码（默认启用，停用需要自己编辑），若您的 Docker 出现问题，不妨用此脚本重新安装说明：因为旧版本的 Docker（如 docker-ce-17.03.0）在执行命令后有比较详细完整的返回结果，适合学习使用，因此脚本提供旧版本的一键安装。{dotted startColor="#7d7dfa" endColor="#7d7dfa"/}2 Docker 一键安装脚本# 脚本创建：闫志聪 # 创建时间：2023-09-15 # 当前版本：v2 #!/bin/bash trap 'mytrap ; exit 1' SIGINT INT # 声明初始化及中断善后函数 function mytrap() { yum -y remove containerd.io docker-buildx-plugin docker-ce docker-ce-cli docker-compose-plugin docker-ce-selinux.noarch \ audit-libs-python checkpolicy container-selinux.noarch docker-ce-rootless-extras fuse-overlayfs \ fuse3-libs libcgroup libsemanage-python policycoreutils-python python-IPy.noarch setools-libs slirp4netns rm -rf /root/docker-ce rm -rf /etc/docker rm -rf /var/lib/docker # rm -rf /etc/yum.repos.d/docker-ce.repo rm -rf /etc/sysctl.d/bridge-iptables.conf # rm -rf /proc/sys/net/bridge/bridge-nf-call-iptables # rm -rf /proc/sys/net/bridge/bridge-nf-call-ip6tables } # 安装 docker-ce-17.03.0 版本 function docker-ce-old () { mkdir /root/docker-ce && cd /root/docker-ce echo -e "\e[0;31m" curl -O https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-17.03.0.ce-1.el7.centos.x86_64.rpm echo curl -O https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-selinux-17.03.0.ce-1.el7.centos.noarch.rpm echo -e "\e[0m" yum -y install docker-ce-17.03.0.ce-1.el7.centos.x86_64.rpm docker-ce-selinux-17.03.0.ce-1.el7.centos.noarch.rpm rm -rf /root/docker-ce if [ ! -d /etc/docker ] ; then mkdir /etc/docker ; fi } # 安装 docker-ce 最新版本 function docker-ce-latest () { yum -y install yum-utils echo -e "\e[0;31m" yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo echo -e "\e[0m" yum --enablerepo=docker-ce-stable -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin if [ ! -d /etc/docker ] ; then mkdir /etc/docker ; fi } # 声明选项判断函数 function option_check () { if [ "$1"=="number" ] ; then flag=$(echo $2 | egrep "1|2") elif [ "$1"=="letter" ] ; then flag=$(echo $2 | egrep "y|n") fi [ -z "$flag" ] && echo -e "\e[1;31m选项输入错误,请重新输入\e[0m" || break } # 版本选择 echo -n -e "\e[0;31m" cat <<EOF 请选择需要安装的 docker-ce 版本: 1、docker-ce-17.03.0 2、docker-ce-latest EOF while true ; do read -p "请输入您的选项:" num ; option_check number $num ; done echo -n -e "\e[0m" # 初始化安装环境 mytrap # 开始安装 case $num in 1) docker-ce-old ;; 2) docker-ce-latest ;; esac # 设置镜像加速站点 while true ; do echo -n -e "\e[0;31m" read -p "请输入您的Docker加速站点:" mirror echo -n -e "\e[0m" [ -z "$mirror" ] && mirror="https://fv6z6xq3.mirror.aliyuncs.com" url=${mirror#*//} ping -c 4 $url 2>/dev/null [ "$?" -ne 0 ] && echo -e "\e[1;31m加速站点不可用,请重新输入\e[0m" || break done cat > /etc/docker/daemon.json <<EOF { "registry-mirrors": ["$mirror"] } EOF # 解决 bridge 和 iptables 的连接问题 echo "1" > /proc/sys/net/bridge/bridge-nf-call-iptables echo "1" > /proc/sys/net/bridge/bridge-nf-call-ip6tables echo "net.bridge.bridge-nf-call-iptables=1" > /etc/sysctl.d/bridge-iptables.conf echo "net.bridge.bridge-nf-call-ip6tables=1" >> /etc/sysctl.d/bridge-iptables.conf #echo -e "\e[0;31m" #sysctl -p /etc/sysctl.d/bridge-iptables.conf #echo -e "\e[0m" systemctl enable docker systemctl start docker run=$(systemctl status docker | grep "active (running)") mirror=$(docker info | grep -A 1 "Registry Mirrors" | grep -v "Registry Mirrors") ufs=$(docker info | grep "Storage Driver" | grep overlay) if [ -z "$run" ] ; then echo -e "\e[0;31mDocker未启动\e[0m" exit 2 elif [ -n "$run" -a -n "$ufs" ] ; then echo -e "Docker运行正常:\e[0;32m$run\e[0m" echo -e "Docker加速站点:\e[0;34m $mirror\e[0m" echo -e "Docker存储驱动:\e[0;31m $ufs\e[0m" exit 0 elif [ -n "$run" -a -z "$ufs" ] ; then echo -e "Docker运行正常:\e[0;32m$run\e[0m" echo -e "Docker加速站点:\e[0;34m $mirror\e[0m" echo -e "\e[0;31mDocker文件系统不是overlay\e[0m" echo -n -e "\e[0;31m" while true ; do read -p "是否修正UFS类型为overlay,y(是),n(否):" let ; option_check letter $let ; done echo -e "\e[0m" case $let in y) echo "overlay" > /etc/modules-load.d/overlay.conf sed -i '/ExecStart/c ExecStart=/usr/bin/dockerd --storage-driver=overlay' systemctl daemon-reload systemctl restart docker ufs1=$(docker info | grep "Storage Driver" | grep overlay) echo -e "Docker存储驱动已修正:\e[0;31m$ufs1\e[0m" exit 0 ;; n) exit 2 ;; esac fi{dotted startColor="#7d7dfa" endColor="#7d7dfa"/}3 使用说明请填写正确的镜像加速站点，不要用脚本中默认的，那是我自己用的！！！若对脚本使用过程有疑问，或脚本执行错误、有更好的意见等，可在后台留言您也可以直接点击此处下载脚本文件：docker-ce-install.sh