坑边闲话:Kubernetes 已经是容器编排领域的事实标准,它将容器运行时和网络模块解放出来,只作为一个编排工具存在。在云原生场景和高可用需求下,容器能跑起来不重要,能编排才重要。

本文将详细介绍:

  • K8S v1.28 的安装与配置
  • K8S Calico 网络配置及其原理
  • K8S 接入 Portainer 管理 UI

1. 安装 Kubernetes·

这里以 Debian 12 为例。

本节内容同时适用于 Master 节点和 Worker 节点。

1.1 添加 Google Kubernetes 上游库并安装 kubeadm·

1
2
3
4
5
6
7
8
9
10
11
12
# 安装必要的 apt 包
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

# 下载 Google Cloud 公开签名秘钥
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 更新 apt 包索引,使之包含新的仓库并安装 kubectl
sudo apt-get update
sudo apt-get install -y kubeadm
sudo apt-mark hold kubelet kubeadm kubectl

注意,因为 K8S 是服务的基础平台,因此 K8S 最好不要随便升级。以上命令的最后一行将 K8S 相关组件

  • kubelet,K8S 核心服务
  • kubeadm,K8S 安装与接入集群
  • kubectl,K8S 命令行工具

均设置为 hold,即忽略对其更新。如果需要更新 K8S,则可以执行以下命令:

1
sudo apt-mark unhold kubelet kubeadm kubectl

随后即可升级 Kubernetes.

1.2 关闭 Swap 内存换入换出机制·

K8S 官方文档认为,如果一台机器准备部署 Kubernetes,则首先应该关闭该机器的交换分区。以下是一些主要原因:

  • 资源分配和调度
    • 预测性: Kubernetes 使用其自己的方式来管理和调度系统资源。如果 swap 被启用,这可能会干扰 Kubernetes 的资源调度算法,导致不可预测的行为。
    • QoS(服务质量): Kubernetes 提供了不同级别的服务质量(QoS)保证。启用 swap 可能会影响这些 QoS 级别的准确性。比如 pod 的调度会以主机的内存占用为触发条件,swap 的存在会使得内存占用降下来,但应用在读取被 swap 的页时却有明显的服务质量降低。
  • 性能
    • 延迟: 使用 swap 通常会增加 I/O 延迟,这对于需要快速响应的应用程序(如数据库和高性能计算应用)是不可接受的。
    • 内存压缩: 现代操作系统和 Kubernetes 有更高效的方式来处理内存压缩和回收,而不是依赖于交换分区。
  • 简化运维
    • 一致性: 禁用 swap 可以简化集群的运维,因为这消除了不同节点可能因为不同的 swap 配置而表现不同的风险。

因此,为了确保 Kubernetes 集群的性能和稳定性,通常建议在安装和运行 Kubernetes 时禁用 swap. 这也是 Kubernetes 官方文档中的推荐做法。

以下是具体操作:

1
2
3
sudo swapoff -a

# 然后注释掉 /etc/fstab 里相关的条目!

由于 Debian 12 默认开启 initramfs 启动,所以需要重新生成开机所需的 initramfs,随后重启即可生效。

1
2
sudo rm /etc/initramfs-tools/conf.d/resume
sudo update-initramfs -u

最后,通过 free -h 查看内存占用,确保没有 swap 条目出现:

1
free -h

1.3 开启内核相关模块·

1.3.1 允许内核检查桥接设备上的流量·

  • modprobe br_netfilter 命令用于在 Linux 系统中加载 br_netfilter 内核模块。该模块是桥接(bridging)网络过滤的一部分,通常用于与 Linux 容器(如 Docker)或虚拟机进行通信,以及在使用 Linux 网桥时进行网络包过滤。加载 br_netfilter 模块后,你可以使用 iptablesnftables 等工具对经过网桥的数据包进行过滤转发拦截。这个模块在一些特定的网络设置中是非常有用的,尤其是当你需要在一个物理主机上运行多个网络隔离的虚拟机或容器时。modprobe br_netfilter 用于启用网桥相关的网络过滤功能,以便你可以更灵活地控制数据包的流动。

为此,首先需要写入配置文件:

1
2
3
4
sudo tee /etc/modules-load.d/k8s.conf <<EOF
overlay
br_netfilter
EOF

随后开启相关模块:

1
2
sudo modprobe overlay
sudo modprobe br_netfilter

1.4 更改 containerdcgroup 驱动·

1
sudo vim /etc/containerd/config.toml

SystemdCgroup 设置为 true,然后重启 containerd

或者直接使用 sed 编辑器进行更改:

1
sudo sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml

2. 安装 Kubenetes:主节点·

1
sudo kubeadm init

随后,可以在屏幕上看到如下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
[init] Using Kubernetes version: v1.25.3
[preflight] Running pre-flight checks
[WARNING SystemVerification]: missing optional cgroups: blkio
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [7060-debian kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.3.1.21]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [7060-debian localhost] and IPs [10.3.1.21 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [7060-debian localhost] and IPs [10.3.1.21 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 13.002231 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
**[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster**
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node 7060-debian as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node 7060-debian as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: wdwmxv.3t113au16je2duss
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

Alternatively, if you are the root user, you can run:

export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.2.1.21:6443 --token 9jkpjo.u0gkcl3gio2tpian \
--discovery-token-ca-cert-hash sha256:2bb7f4b79a1ddecce4178c57326f7fada315649f076f43d5452eab4e1722cae8

牢记最后一行输出,接下来要在其他服务器上用到。

如果失败了该怎么办? 很多新手第一步安装可能会遇到一些麻烦,比如因为某些环节没有做到位,导致安装失败。此时重新运行程序发现有些文件已经存在,无法继续安装。此时,可以通过 sudo kubeadm reset 命令回到 kubeadm init 之前的状态。

2.1 复制 key 文件到家目录·

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

2.2 生成 kubectlzsh 补全脚本·

1
2
3
4
5
kubectl completion zsh > ~/.zsh/kubectl_auto_completion.sh
kubeadm completion zsh > ~/.zsh/kubeadm_auto_completion.sh
echo 'source ~/.zsh/kubectl_auto_completion.sh' >> ~/.zshrc
echo 'source ~/.zsh/kubeadm_auto_completion.sh' >> ~/.zshrc
source ~/.zshrc

2.3 安装 Calico 网络插件·

Calico 在 Kubernetes(K8s)中的工作原理

  • 网络连接
    1. Pod 网络:Calico 为每个 Kubernetes Pod 分配一个 IP 地址,并确保 Pod 之间可以直接通信,无需 NAT.
    2. 路由广播:Calico 使用 BGP(边界网关协议)或其内部的路由机制来广播路由信息,以便节点(Node)之间能够相互通信。
    3. 跨节点通信:Calico 自动处理跨多个物理节点的 Pod 通信。
  • 网络策略
    1. 网络隔离:Calico 可以定义精细的网络策略,以控制哪些 Pod 可以相互通信。
    2. 安全组:除了基本的网络策略外,Calico 还支持更高级的安全特性,如安全组。
  • 性能和扩展性
    1. 高性能:Calico 采用的是非常接近于裸机性能的数据平面,因此在大规模集群中表现优越。
    2. 扩展性:Calico 可以轻松地扩展到非常大的集群和多种环境(混合云、多云等)。
  • 其他特性
    1. 双栈网络:Calico 支持 IPv4 和 IPv6,可以在同一个集群中同时使用。
    2. 集成与兼容性:Calico 可以与其他 Kubernetes 组件和 CNI 插件(如 Istio、EKS、GKE 等)无缝集成。
    3. 多数据平面选项:Calico 提供了多种数据平面选项,包括纯 Linux 数据平面、eBPF 数据平面和 Windows 数据平面。

通过这些特性和机制,Calico 提供了一个强大、灵活和安全的网络解决方案,适用于各种规模和类型的 Kubernetes 集群。

1
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

3. 将工作节点加入集群·

1
2
sudo kubeadm join 10.2.1.21:6443 --token 9jkpjo.u0gkcl3gio2tpian \
--discovery-token-ca-cert-hash sha256:2bb7f4b79a1ddecce4178c57326f7fada315649f076f43d5452eab4e1722cae8

4. 删除 Kubernetes·

1
2
3
4
sudo rm -rf /etc/systemd/system/kubelnet.service.d
sudo rm -fr /etc/kubernetes
sudo rm -fr /var/lib/etcd
sudo apt remove --purge kubelet kubeadm kubectl

总结·

本文介绍了 K8S 相关的一些安装和简单配置相关的内容,作为一个企业级高可用、云原生解决方案,K8S 是复杂的,通过短时间的学习做到精通基本不可能,需要持之以恒的钻研、学习。