1.准备工作(我这里使用 ESXi 7.0 U2 创建虚拟机)
- cpu 8c
- 内存 8g
- 系统 debain 12
- ip 192.168.xxx.70
2.开始部署
关闭 swap
sed -ri 's/^([^#].*swap.*)$/#\1/' /etc/fstab && grep swap /etc/fstab && swapoff -a && free -h如果安装了防火墙请关闭防火墙
ufw disable开启ipv4转发
cat <<EOF | sudo tee /etc/sysctl.d/k8s.confnet.ipv4.ip_forward = 1EOFsysctl --systemsysctl net.ipv4.ip_forward设置hostname
nano /etc/hostnamedebain-master设置host
nano /etc/hosts
127.0.0.1 localhost127.0.1.1 debain-master
# The following lines are desirable for IPv6 capable hosts::1 localhost ip6-localhost ip6-loopbackff02::1 ip6-allnodesff02::2 ip6-allrouters安装containerd
apt update && apt install -y containerd查看containerd版本
containerd -v
root@debian:~# containerd -vcontainerd github.com/containerd/containerd 1.6.20~ds1 1.6.20~ds1-1+deb12u1生成默认containerd配置文件
mkdir -p /etc/containerd && containerd config default>/etc/containerd/config.toml编辑配置文件
nano /etc/containerd/config.toml
修改plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes.runc.options 的 SystemdCgroup = fales 为 true
修改sandbox_image = “registry.k8s.io/pause:3.6” 为sandbox_image = “registry.aliyuncs.com/google_containers/pause:3.9”
disabled_plugins = []imports = []oom_score = 0plugin_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 sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9" 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 = "" 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".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.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 = ""
[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重启 containerd 服务
systemctl restart containerdsystemctl enable containerd添加Kubernetes GPG 密钥
apt install -y apt-transport-https ca-certificates curl gpgcurl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpgchmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg添加 Kubernetes apt 仓库
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list更新apt源 安装 kubeadm, kubelet, kubectl 并禁止更新
apt update && \apt install -y kubelet kubectl kubeadm && \apt-mark hold kubelet kubeadm kubectl验证安装
root@debian:~# kubectl versionClient Version: v1.32.5Kustomize Version: v5.5.0The connection to the server localhost:8080 was refused - did you specify the right host or port?root@debian:~# kubelet versionE0601 12:25:40.197825 18045 run.go:72] "command failed" err="unknown command version"root@debian:~# kubeadm versionkubeadm version: &version.Info{Major:"1", Minor:"32", GitVersion:"v1.32.5", GitCommit:"9894294ef13a5b32803e3ca2c0d620a088cc84d1", GitTreeState:"clean", BuildDate:"2025-05-15T09:10:46Z", GoVersion:"go1.23.8", Compiler:"gc", Platform:"linux/amd64"}生成初始化节点配置文件
kubeadm config print init-defaults > kubeadm-config.yaml编辑配置
nano kubeadm-config.yaml将advertiseAddress: 1.2.3.4 修改为 advertiseAddress: 192.168.xxx.70 (修改为你的master节点ip地址)
将nodeRegistration 中的 name 修改为你的master 节点的主机名
在networking 中添加 podSubnet: 10.244.0.0/16
将imageRepository: registry.k8s.io 修改为imageRepository: registry.aliyuncs.com/google_containers
apiVersion: kubeadm.k8s.io/v1beta4bootstrapTokens:- groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authenticationkind: InitConfigurationlocalAPIEndpoint: advertiseAddress: 192.168.xxx.70 bindPort: 6443nodeRegistration: criSocket: unix:///var/run/containerd/containerd.sock imagePullPolicy: IfNotPresent imagePullSerial: true name: debain-master taints: nulltimeouts: controlPlaneComponentHealthCheck: 4m0s discovery: 5m0s etcdAPICall: 2m0s kubeletHealthCheck: 4m0s kubernetesAPICall: 1m0s tlsBootstrap: 5m0s upgradeManifests: 5m0s---apiServer: {}apiVersion: kubeadm.k8s.io/v1beta4caCertificateValidityPeriod: 87600h0m0scertificateValidityPeriod: 8760h0m0scertificatesDir: /etc/kubernetes/pkiclusterName: kubernetescontrollerManager: {}dns: {}encryptionAlgorithm: RSA-2048etcd: local: dataDir: /var/lib/etcdimageRepository: registry.aliyuncs.com/google_containerskind: ClusterConfigurationkubernetesVersion: 1.32.0networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 podSubnet: 10.244.0.0/16proxy: {}scheduler: {}初始化节点
kubeadm init --config kubeadm-config.yaml --upload-certs --v=9初始化成功以后运行
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config安装Calico
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.1/manifests/tigera-operator.yaml
wget https://github.moeyy.xyz/https://raw.githubusercontent.com/projectcalico/calico/v3.30.1/manifests/custom-resources.yaml修改custom-resources.yaml
nano custom-resources.yaml将cidr 修改为在kubeadm-config.yaml 中定义的 podSubnet: 10.244.0.0/16 -> cidr: 10.244.0.0/16/16
在spec 中添加镜像registry: docker.m.daocloud.io
# This section includes base Calico installation configuration.# For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.InstallationapiVersion: operator.tigera.io/v1kind: Installationmetadata: name: defaultspec: # Configures Calico networking. registry: docker.m.daocloud.io # <-- 添加或修改此行! calicoNetwork: ipPools: - name: default-ipv4-ippool blockSize: 26 cidr: 10.244.0.0/16 encapsulation: VXLANCrossSubnet natOutgoing: Enabled nodeSelector: all()
---
# This section configures the Calico API server.# For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.APIServerapiVersion: operator.tigera.io/v1kind: APIServermetadata: name: defaultspec: {}
---
# Configures the Calico Goldmane flow aggregator.apiVersion: operator.tigera.io/v1kind: Goldmanemetadata: name: default
---
# Configures the Calico Whisker observability UI.apiVersion: operator.tigera.io/v1kind: Whiskermetadata: name: defaultapply
kubectl create -f custom-resources.yaml
Every 2.0s: kubectl get pods -n calico-system
NAME READY STATUS RESTARTS AGEcalico-kube-controllers-77f646f8d9-6dlkw 1/1 Running 0 4m20scalico-node-5n2cp 1/1 Running 0 4m23scalico-typha-b6c4c4db5-lmkc6 1/1 Running 0 4m25scsi-node-driver-cklfv 2/2 Running 0 4m22sgoldmane-795ddb994b-vssfw 1/1 Running 0 4m26swhisker-7cc794bddb-dt4ms 2/2 Running 0 2m44s可用性验证
root@debain-master:~# kubectl get svc -n kube-systemNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 58mroot@debain-master:~# dig -t a www.bilibili.com @10.96.0.10
; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> -t a www.bilibili.com @10.96.0.10;; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16904;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 1232; COOKIE: 4138133d6f05ec22 (echoed);; QUESTION SECTION:;www.bilibili.com. IN A
;; ANSWER SECTION:www.bilibili.com. 30 IN A 111.6.167.135www.bilibili.com. 30 IN A 111.6.167.136www.bilibili.com. 30 IN A 111.6.167.134www.bilibili.com. 30 IN A 111.6.167.137
;; Query time: 0 msec;; SERVER: 10.96.0.10#53(10.96.0.10) (UDP);; WHEN: Sun Jun 01 14:02:24 CST 2025;; MSG SIZE rcvd: 185