部署Kubernetes 1.25 (containerd) - 无坑部署

本文详细介绍了如何在MacOS M系列(arm64)及CentOS AMD64系统上部署Kubernetes 1.25,包括containerd、crictl的安装配置,kubeadm初始化,calico网络插件安装,以及节点的加入和IPVS模式切换。此外,还提供了一键部署脚本,可在5分钟内完成部署。
摘要由CSDN通过智能技术生成

在本文中,我将详细介绍如何部署Kubernetes1.25版本。这篇文章汇集了我个人的部署经验和实践,内容既实用又具有一定的学习值。
最初,这篇文章是为了在我的MacOS M系列(arm64)电脑上部署Kubernetes而编写的。经过不断的测试和改进,这一方法同样适用于生产环境中的部署,例如在CentOSAMD64系统上。当然,这些方法也适用于其他Linux发行版,只需适当调整某些命令即可。

跟着本文章走绝对可以部署K8s;

为了方便快捷的部署,文末我将提供一个一键部署脚本,可以在大约5分钟内完成Master或Node节点的完整部署

为了更好地学习和实践,我们将从本地部署开始。虽然您也可以选择在云平台上操作,但本文主要探讨如何在MacOS M系列(arm64)上通过虚拟机部署CentOS。我已经在Mac虚拟机上部署CentOS花费了不少时间并解决了众多问题。当然,本文的方法也适用于非Mac或非arm64架构的设备

接下来,本文内容将分为以下几个部分进行详细介绍:

  • 前期准备:MacOS M系列(arm64)安装虚拟机并运行CentOS 7系统
    • 包括集群规划和虚拟机创建过程(上面教程不只仅限MacOS)。
  • 服务器配置:Kubernetes 1.25 相关配置 - 系统篇
    • 涵盖开启SSH服务、配置静态IP、编辑hosts文件、关闭防火墙和SELinux、禁用Swap、系统参数优化、配置Linux内核模块和参数(例如调整文件打开数等),IPVS设置,添加YUM源,以及设置时间同步(使用Chrony作为NTP服务器,可选)。
  • 搭建集群:(本文)
    • 介绍安装containerd,配置containerd,安装和配置crictl,以及安装Kubernetes 1.25版本的kubectl、kubelet和kubeadm,初始化master集群,生成kubeadm默认配置文件,设置.kube/config,安装Calico网络插件,添加Node节点,并切换Kubernetes的IPVS转发模式。
  • 扩展功能:
    • 包括部署Traefik,安装NFS存储,安装KubeSphere,安装Grafana,以及部署EFK(Elasticsearch + Filebeat + Kibana)日志收集系统。
  • 相关笔记:
    • 整理在部署过程中遇到的问题及其解决方案,以及如何部署Filebeat。

进阶教程

接下来的阶段,我会接着更新:

  • 扩展功能:
    • 包括部署Traefik,安装NFS存储,安装KubeSphere,安装Grafana,以及部署EFK(Elasticsearch + Filebeat + Kibana)日志收集系统。
  • 相关笔记:
    • 整理在部署过程中遇到的问题及其解决方案,以及如何部署Filebeat。
  • 额外内容:
    • 部署各种中间件,部署主从数据库,部署高可用kafka,部署高可用HA-Hadoop,redis等等…
  • 自动化部署脚本:
    • 五分钟内完成从0到1搭建;

1. 安装containerd

yum install containerd -y
systemctl enable containerd.service

👇👇👇👇
在这里插入图片描述

2. 配置

此命令通常在初始化 containerd 配置或修改默认配置时使用。它可以快速创建一个标准的配置文件,可以在此基础上进行修改,以适应特定的需求或环境。

containerd config default | tee /etc/containerd/config.toml

2.1 配置config

  • 下面注意,注意pause版本,我这里安装 k8s 1.25选择了 pause版本3.8
  • sandbox_image = “registry.aliyuncs.com/google_containers/pause:3.8”
  • 下面配置中plugins的源我已经切换国内了,如果有其他需求可以自行更改
cat > /etc/containerd/config.toml << EOF
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
temp = ""
version = 2

[cgroup]
  path = ""

[debug]
  address = ""
  format = ""
  gid = 0
  level = ""
  uid = 0

[grpc]
  address = "/run/containerd/containerd.sock"
  gid = 0
  max_recv_message_size = 16777216
  max_send_message_size = 16777216
  tcp_address = ""
  tcp_tls_ca = ""
  tcp_tls_cert = ""
  tcp_tls_key = ""
  uid = 0

[metrics]
  address = ""
  grpc_histogram = false

[plugins]

  [plugins."io.containerd.gc.v1.scheduler"]
    deletion_threshold = 0
    mutation_threshold = 100
    pause_threshold = 0.02
    schedule_delay = "0s"
    startup_delay = "100ms"

  [plugins."io.containerd.grpc.v1.cri"]
    device_ownership_from_security_context = false
    disable_apparmor = false
    disable_cgroup = false
    disable_hugetlb_controller = true
    disable_proc_mount = false
    disable_tcp_service = true
    enable_selinux = false
    enable_tls_streaming = false
    enable_unprivileged_icmp = false
    enable_unprivileged_ports = false
    ignore_image_defined_volumes = false
    max_concurrent_downloads = 3
    max_container_log_line_size = 16384
    netns_mounts_under_state_dir = false
    restrict_oom_score_adj = false
    
    # 注释上面那行,添加下面这行,注意pause版本
    sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.8"
    
    selinux_category_range = 1024
    stats_collect_period = 10
    stream_idle_timeout = "4h0m0s"
    stream_server_address = "127.0.0.1"
    stream_server_port = "0"
    systemd_cgroup = false
    tolerate_missing_hugetlb_controller = true
    unset_seccomp_profile = ""

    [plugins."io.containerd.grpc.v1.cri".cni]
      bin_dir = "/opt/cni/bin"
      conf_dir = "/etc/cni/net.d"
      conf_template = ""
      ip_pref = ""
      max_conf_num = 1

    [plugins."io.containerd.grpc.v1.cri".containerd]
      default_runtime_name = "runc"
      disable_snapshot_annotations = true
      discard_unpacked_layers = false
      ignore_rdt_not_enabled_errors = false
      no_pivot = false
      snapshotter = "overlayfs"

      [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
        base_runtime_spec = ""
        cni_conf_dir = ""
        cni_max_conf_num = 0
        container_annotations = []
        pod_annotations = []
        privileged_without_host_devices = false
        runtime_engine = ""
        runtime_path = ""
        runtime_root = ""
        runtime_type = ""

        [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]

      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]

        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
          base_runtime_spec = ""
          cni_conf_dir = ""
          cni_max_conf_num = 0
          container_annotations = []
          pod_annotations = []
          privileged_without_host_devices = false
          runtime_engine = ""
          runtime_path = ""
          runtime_root = ""
          runtime_type = "io.containerd.runc.v2"

          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
            BinaryName = ""
            CriuImagePath = ""
            CriuPath = ""
            CriuWorkPath = ""
            IoGid = 0
            IoUid = 0
            NoNewKeyring = false
            NoPivotRoot = false
            Root = ""
            ShimCgroup = ""
            # 下面目的是指定使用 systemd 作为 cgroup 的管理器
            SystemdCgroup = true

      [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
        base_runtime_spec = ""
        cni_conf_dir = ""
        cni_max_conf_num = 0
        container_annotations = []
        pod_annotations = []
        privileged_without_host_devices = false
        runtime_engine = ""
        runtime_path = ""
        runtime_root = ""
        runtime_type = ""

        [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]

    [plugins."io.containerd.grpc.v1.cri".image_decryption]
      key_model = "node"

    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = ""

      [plugins."io.containerd.grpc.v1.cri".registry.auths]

      [plugins."io.containerd.grpc.v1.cri".registry.configs]

      [plugins."io.containerd.grpc.v1.cri".registry.headers]

      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          #endpoint = ["https://registry-1.docker.io"]
          # 注释上面那行,添加下面三行
          endpoint = ["https://docker.mirrors.ustc.edu.cn"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
          endpoint = ["https://registry.aliyuncs.com/google_containers"]


    [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
      tls_cert_file = ""
      tls_key_file = ""

  [plugins."io.containerd.internal.v1.opt"]
    path = "/opt/containerd"

  [plugins."io.containerd.internal.v1.restart"]
    interval = "10s"

  [plugins."io.containerd.internal.v1.tracing"]
    sampling_ratio = 1.0
    service_name = "containerd"

  [plugins."io.containerd.metadata.v1.bolt"]
    content_sharing_policy = "shared"

  [plugins."io.containerd.monitor.v1.cgroups"]
    no_prometheus = false

  [plugins."io.containerd.runtime.v1.linux"]
    no_shim = false
    runtime = "runc"
    runtime_root = ""
    shim = "containerd-shim"
    shim_debug = false

  [plugins."io.containerd.runtime.v2.task"]
    platforms = ["linux/amd64"]
    sched_core = false

  [plugins."io.containerd.service.v1.diff-service"]
    default = ["walking"]

  [plugins."io.containerd.service.v1.tasks-service"]
    rdt_config_file = ""

  [plugins."io.containerd.snapshotter.v1.aufs"]
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.btrfs"]
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.devmapper"]
    async_remove = false
    base_image_size = ""
    discard_blocks = false
    fs_options = ""
    fs_type = ""
    pool_name = ""
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.native"]
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.overlayfs"]
    root_path = ""
    upperdir_label = false

  [plugins."io.containerd.snapshotter.v1.zfs"]
    root_path = ""

  [plugins."io.containerd.tracing.processor.v1.otlp"]
    endpoint = ""
    insecure = false
    protocol = ""

[proxy_plugins]

[stream_processors]

  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
    accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
    env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
    path = "ctd-decoder"
    returns = "application/vnd.oci.image.layer.v1.tar"

  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
    accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
    env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
    path = "ctd-decoder"
    returns = "application/vnd.oci.image.layer.v1.tar+gzip"

[timeouts]
  "io.containerd.timeout.bolt.open" = "0s"
  "io.containerd.timeout.shim.cleanup" = "5s"
  "io.containerd.timeout.shim.load" = "5s"
  "io.containerd.timeout.shim.shutdown" = "3s"
  "io.containerd.timeout.task.state" = "2s"

[ttrpc]
  address = ""
  gid = 0
  uid = 0
EOF

确保容器运行时环境(containerd)的配置更新能够正确应用,并重新启动服务以使这些更改生效:

systemctl daemon-reload
systemctl restart containerd

3. 安装crictl

主要目的是为了提供一个命令行界面来与容器运行时的 CRI(容器运行时接口)进行交互。在 Kubernetes 集群管理中尤为重要;

因为我是arm64架构下载了arm版本。如果是amd64则执行amd64 相关的命令;

# arm64 版本
wget https://kubernetes-1251060623.cos.ap-shanghai.myqcloud.com/crictl/v1.24.2/crictl-v1.24.2-linux-arm64.tar.gz
tar -zxf crictl-v1.24.2-linux-arm64.tar.gz
mv crictl /usr/local/bin/ 

# amd64 版本
wget https://kubernetes-1251060623.cos.ap-shanghai.myqcloud.com/crictl/v1.24.2/crictl-v1.24.2-linux-amd64.tar.gz
tar -zxf crictl-v1.24.2-linux-amd64.tar.gz 
mv crictl /usr/local/bin/

编写配置文件

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

4. 安装1.25版本的kubectl kubelet kubeadm

sudo yum install -y kubelet-1.25.0 kubeadm-1.25.0 kubectl-1.25.0
systemctl start kubelet.service
systemctl enable kubelet.service

到这里,完成了系统配置和k8s配置了,现在又可以克隆系统了,从此后可以在新克隆的系统中选择master和node节点了
到这里,完成了系统配置和k8s配置了,现在又可以克隆系统了,从此后可以在新克隆的系统中选择master和node节点了
到这里,完成了系统配置和k8s配置了,现在又可以克隆系统了,从此后可以在新克隆的系统中选择master和node节点了


5. 初始化master集群

使用 kubeadm 工具生成默认的 Kubernetes 集群初始化配置文件

kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml

上面命令执行后,/root根目录下产生kubeadm.yml文件,修个这个文件修改配置文件

  • 修改imageRepository,改为aliyun的镜像仓库地址

  • 如果需要修改nodeRegistrationtaints(非必需,根据需求选择)

    • 我的配置中effect设置了NoSchedule这意味着带有这个 taint 的节点将不会调度那些没有相应 toleration 的 Pod。具体来说,node-role.kubernetes.io/master 这个 taint 通常用于 master(控制平面)节点,以防止一般的工作负载被调度到这些节点上,从而确保控制平面的资源不被一般的 Pod 使用。
  • 修改networking中的podSubnet以及serviceSubnet(没有则添加),根据的自己的环境进行设置

    • podSubnet定义了 Pod 网络的 IP 地址范围。这个范围被用于分配给集群中的每个 Pod IP 地址。
    • serviceSubnet 定义了 Kubernetes Service 对象的虚拟 IP 地址范围。这个范围用于分配给 Service 的 IP 地址。
  • 设置cgroupDriversystemd,非必要

  • 修改advertiseAddress为正确的Master的IP地址或者0.0.0.0(不推荐0.0.0.0 意味着监听所有接口上的流量)

  • 修改nodeRegistrationname 为k8s-matser名称(master中就是设置的hostname,我当前k8s-master)

修改后的配置文件(下面是一个样例,根据我上面所说的和自己的实际需求去配置)

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 10.211.55.100
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  name: k8s-master
  taints:
	- effect: NoSchedule
  	  key: node-role.kubernetes.io/master

---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.25.0
networking:
  dnsDomain: cluster.local
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd

6. 生成kubeadm默认配置文件

在master中执行,node跳过

kubeadm init --config=kubeadm.yml --upload-certs 

如果配置错误可以使用 kubeadm reset -f 重置集群记得 node节点也要重置一下

日志中看到这行表示成功
👇👇👇
在这里插入图片描述
记着上面的集群令牌kubeadm join 10.211.55.100:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:ed8b37e76c33c9ffec98f89816d6c9f8a6c616b2f80aab30da2aacb1ec382b0a,等会需要使用!!

7. 设置.kube/config

想要哪个用户使用k8s就在哪个用户上面配置一下(master或node,甚至宿主机)

下面是master的配置;

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

编辑vim /etc/profile添加一行

export KUBECONFIG=/etc/kubernetes/admin.conf

保存后刷新profile

source /etc/profile

8. calico网络插件安装

安装 Calico 网络插件在 Kubernetes 集群中的主要目的是提供网络功能,确保 pod 间和外部世界的通信
master中设置

下面👇根据自己的配置自行选择下载链接;

# 官方部署
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

# 国内镜像版本(arm64 架构)
kubectl apply -f https://kubernetes-1251060623.cos.ap-shanghai.myqcloud.com/yaml/calico/v3.26.1/calico_arm.yaml

# 国内镜像版本(amd64 架构)
kubectl apply -f https://kubernetes-1251060623.cos.ap-shanghai.myqcloud.com/yaml/calico/v3.26.1/calico_amd.yaml

在master查看状态

kubectl get pods -A

👇👇👇
在这里插入图片描述

9. node加入节点

从master中copy两个系统镜像,我这先配置node1,最后从node1中copy一个node2配置hostname和ip就可以

进入node1的ssh

9.1 设置主机名称

sudo hostnamectl set-hostname k8s-node1

9.2 修改静态ip

查找连接名称 nmcli con show

查询出当前运行中的静态网卡配置为:static-enp0s5

修改 IP 地址: nmcli con mod static-enp0s5 ipv4.addresses 10.211.55.101/24 这里的ip根据自己的实际情况来定

重新启动网络连接

nmcli con up static-enp0s5

👇👇👇
在这里插入图片描述
上面配置完成后,ssh会断开链接,根据刚刚设置的新的静态Ip地址来重新登陆Node节点;

9.3 节点加入

使用刚刚的集群令牌在node节点上执行加入集群,node1、node2一样

kubeadm join 10.211.55.100:6443 --token abcdef.0123456789abcdef \
	--discovery-token-ca-cert-hash sha256:ed8b37e76c33c9ffec98f89816d6c9f8a6c616b2f80aab30da2aacb1ec382b0a

👇👇👇
在这里插入图片描述
加入后在master节点上查看状态

kubectl get nodes

👇👇👇
在这里插入图片描述

node节点加入集群的令牌有效期为24小时,可以在master节点生产新的令牌

kubeadm token create --print-join-command

9.2.1 设置token用不过期(可选)

当前token 默认24小时过期,因此测试环境下可以设置用不过期

在master主机上,先查看存在的token

kubeadm token list

生成用不过期的token

kubeadm token create --ttl 0

获取token,然后生成哈希值

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

最后在节点上(token your-token替换新生成的token;your-ca-cert-hash替换上面命令生成的hash值)

kubeadm join 192.168.1.101:6443 --token your-token --discovery-token-ca-cert-hash sha256:your-ca-cert-hash

删除token的命令(如果需要)

kubeadm token delete [token]

10. 将k8s切换为ipvs转发模式

主要是为了提高服务转发的性能和扩展性。IPVS 是基于 Netfilter(Linux 内核的网络包过滤框架)的传输层负载均衡技术,适用于处理大量并发连接,特别是在大规模集群环境中

在master节点上修改配置

kubectl -n kube-system edit cm kube-proxy

找到mode:更改为mode: “ipvs”

找到metricsBindAddress: 更改为 metricsBindAddress: “127.0.0.1:10249”

  • IP 地址: 这应该是节点上的一个有效的、可访问的 IP 地址。这可以是本地环回地址(127.0.0.1)用于仅在本地访问性能指标,也可以是节点的公共或私有网络地址,以便在网络中的其他位置访问性能指标。
  • 端口号: 需要指定一个未被占用的端口号。通常,默认的端口号是 10249,但可以根据需要选择不同的端口。
    👇👇👇
    在这里插入图片描述
    将原来的kube-proxy删除,重启
kubectl -n kube-system get pod -l k8s-app=kube-proxy | grep -v 'NAME' | awk '{print $1}' | xargs kubectl -n kube-system delete pod

11. 配置kubectl TAB补全功能

这是一个可选项,目的是为了终端方便操作kubectl相关命令

yum install bash-completion -y
source /usr/share/bash-completion/bash_completion 
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

到这里整个k8s集群环境就基本搭建完成了!!!

注意

  • 安装时注意自己安装的程序版本
  • 一般安装不会在胜利,会出现不少问题,用tail -f /var/log/messages跟踪下日志
  • 最好把几台机器系统时间同步下,节点通讯中的token与时间也有关
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值