2024-08-13-Wed-T-Kubernetes搭建

基于Ubuntu 24.04 快速部署K8S 1.31.0集群

1. K8S集群主机准备

主机操作系统版本: Ubuntu 24.04

硬件配置说明:
master 2核 4G内存 20GB硬盘
node1 2核 4G内存 20GB硬盘
node2 2核 4G内存 20GB硬盘

1.1 主机名配置

master: hostnamectl set-hostname k8s-master01
node1: hostnamectl set-hostname k8s-worker01
node2: hostnamectl set-hostname k8s-worker02

1.2 主机IP地址配置

vim /etc/netplan/50-cloud-init.yaml

1
静态配置

欲使其生效, 使用命令netplan apply

查看IP地址: ip a s

使用动态分配时, 修改hosts即可

vim /etc/hosts

1
2
3
192.168.64.15 k8s-master01
192.168.64.16 k8s-worker01
192.168.64.17 k8s-worker02

1.3 时间同步

apt install ntpsec-ntpdate

  • 手动同步: ntpdate ntp.aliyun.com

  • 自动同步: 编辑 crontab -e 定时任务

1
2
0 0 * * *ntpdate ntp.aliyun.com
# 每天0点0分时间同步

1.4 配置内核转发和网桥过滤

如果不配置会导致K8S集群的网络通信不流畅

创建加载内核模块文件

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
# 手动加载overlay和br_netfilter, 为了避免重启系统, 本文采用手动加载
modprobe overlay
modprobe br_netfilter
# modprobe overlay 是用于在 Linux 系统中加载 overlay 文件系统模块的命令。具体来说:
# modprobe:是一个工具,用于加载或卸载内核模块。它会自动处理模块间的依赖关系。
# overlay:指的是 overlay 文件系统模块,是一种联合文件系统(union filesystem),允许你将一个文件系统(通常是只读的)与另一个
# 文件系统(通常是可写的)合并,使之对外表现为单一的文件系统。
# 作用:
# 运行 modprobe overlay 后,系统会尝试加载 overlay 模块,提供支持 联合挂载,这种挂载方式允许:
# 存储层的组合:将多个文件系统(或称层)“叠加”成一个文件系统。
# Docker和Kubernetes等容器技术使用:容器中使用 overlayfs 提供文件隔离和更高效的存储管理。
# 这种联合文件系统特别适用于容器技术,比如 Docker,它利用 overlayfs 来高效管理镜像层和容器层。
#
#自动加载overlay和br_netfilter
cat << EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# 这个命令的整体作用是在 /etc/modules-load.d/k8s.conf 文件中添加以下内容
# 这样,系统每次启动时都会自动加载 overlay 和 br_netfilter 模块,从而满足 Kubernetes 和其他容器服务的网络要求。
# 添加网桥过滤及内核转发配置文件

cat << EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# net.bridge.bridge-nf-call-ip6tables = 1:这个参数允许 IPv6 的网络桥接流量被 ip6tables 进行处理。设为 1 表示开启。
# net.bridge.bridge-nf-call-iptables = 1:这个参数允许 IPv4 的网络桥接流量被 iptables 进行处理。设为 1 表示开启。这对于 Kubernetes 的网络策略和防火墙规则是必要的。
# net.ipv4.ip_forward = 1:这个参数启用 IPv4 的转发功能。设为 1 表示开启。这对于容器间的网络通信以及外部访问容器的服务是必需的。


# 欲使之生效, 还需键入命令
sysctl --system

1.5 安装ipset和ipvsadm

后续在使用kubeproxy的代理模式时, 会用到ipvs的配置
ipset 和 ipvsadm 是用于网络流量管理和负载均衡的重要工具,特别是在 Linux 环境中
ipset 是一个用于管理 IP 集合的工具。它可以创建和维护多个 IP 地址的集合,以便于快速地在防火墙(如 iptables)中进行匹配。ipset 的主要用途包括:
性能优化:通过将多个 IP 地址组合成集合,ipset 提供了比单独规则更高效的匹配方式,减少了 iptables 规则的数量,从而提高了性能。
动态管理:可以在运行时添加、删除或修改 IP 集合,便于对大规模流量的快速响应。

ipvsadm(“IP Virtual Server Administration”) 是 IP 虚拟服务器(IPVS)的管理工具,用于实现 Linux 的负载均衡。它主要用于以下方面:
负载均衡:ipvsadm 允许用户配置和管理 IPVS,以实现对传入流量的负载均衡。通过将请求分发到多个后端服务器,提供高可用性和高性能。
调度算法:支持多种负载均衡算法(如轮询、最少连接、基于权重等),使得流量分发更加灵活。
高可用性:配合 Linux 虚拟服务器(如 LVS),能够实现高可用性架构,支持多种网络协议(如 TCP、UDP)。

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
# 安装 ipset 和 ipvsadm
apt install ipset ipvsadm

# 配置ipvsadm模块加载
# 添加需要加载的模块

cat << EOF | tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF

# 创建加载模块脚本文件, 立即使用
cat << EOF | tee ipvs.sh
#! /bin/sh
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack
EOF

# 执行脚本
sh ipvs.sh

# 查看模块加载情况
lsmod | grep "ip_vs"

1.6 关闭SWAP分区

1
2
3
4
5
6
7
8
9
# 如果不重启式的关闭swap分区, 可以临时关闭, 关闭命令为
swapoff -a
# 永远关闭swap分区, 需要重启系统
vim /etc/fstab
# 注释掉如下内容
# /swap.img none swap sw 0 0



2. K8S集群节点容器管理工具准备

2.1 Containerd 部署文件获取

1
2
3
4
5
6
7
8
# 通过wget命令下载
# wget https://github.com/containerd/containerd/releases/download/v1.7.20/cri-containerd-1.7.20-linux-amd64.tar.gz
# 本文使用Macbook M1芯片, 所以使用arm版本
wget https://github.com/containerd/containerd/releases/download/v1.7.20/cri-containerd-1.7.20-linux-arm64.tar.gz

# 解压并合并到根目录
tar xfv cri-containerd-1.7.20-linux-arm64.tar.gz -C /

Containerd配置文件生成和修改

默认情况下, 没有containerd配置文件, 我们需要使用命令生成并进行自定义修改

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
# 创建配置文件目录
mkdir /etc/containerd

# 生成配置文件
containerd config default > /etc/containerd/config.toml

# 修改第67行
vim /etc/containerd/config.toml
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.10" # 修改为阿里云镜像
# sandbox_image = "registry.k8s.io/pause:3.9" # 由3.8修改为3.9

# 修改第139行, runc的operation
vim /etc/containerd/config.toml
SystemdCgroup = true # 由false修改为true


# containerd启动及开机自启动设计

# 设置开机自启动, 并现在启动
systemctl enable --now containerd

# 验证启动成功
ls /var/run/containerd/ -l
# 如果成功, 则有以下内容
# srw-rw---- 1 root root 0 Nov 4 10:17 containerd.sock
# srw-rw---- 1 root root 0 Nov 4 10:17 containerd.sock.ttrpc
# drwx--x--x 2 root root 40 Nov 4 10:17 io.containerd.runtime.v1.linux
# drwx--x--x 2 root root 40 Nov 4 10:17 io.containerd.runtime.v2.task


# 验证版本
containerd --version

3. K8S 集群部署

3.1 安装源: apt

1
2
3
4
5
6
7
8
9
10
11
12

# 下载用于Kubernetes软件包仓库的公共签名密钥, 如果没有此密钥, 则无法完成软件安装包的安装
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /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.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 更新apt包索引

sudo apt-get update

3.2 Kubernetes软件安装及kubelet配置

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
# 查看当前软件列表, 是否有kubeadm
apt-cache policy kubeadm

# 安装指定版本
apt install kubeadm=1.31.0-1.1 kubelet=1.31.0-1.1 kubectl=1.31.0-1.1 -y
# !!!注意: 安装完成后不能立即启动

# 首先锁定这些应用的版本, 保证后续使用过程中不会自动更新, 取消锁定使用unhold
sudo apt-mark hold kubeadm kubelet kubectl

# 配置kubelet
# 为实现Kubernetes使用的cgroup与容器运行时使用的cgroupdriver的一致性, 建议修改如下内容
vim /etc/default/kubelet
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

# 设置为开机自启动即可, 由于没有生成配置文件, 集群初始化后自动启动
systemctl enable kubelet


# 准备初始化的配置文件, 只需要在master节点中准备即可
# 查看版本 kubeadm version
# 生成部署配置文件
kubeadm config print init-defaults > kubeadm-config.yaml
#修改配置文件
vim kubeadm-config.yaml
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
# 修改第12行, 18行的内容, 在46后增加一行podSubnet

1 apiVersion: kubeadm.k8s.io/v1beta4
2 bootstrapTokens:
3 - groups:
4 - system:bootstrappers:kubeadm:default-node-token
5 token: abcdef.0123456789abcdef
6 ttl: 24h0m0s
7 usages:
8 - signing
9 - authentication
10 kind: InitConfiguration
11 localAPIEndpoint:
12 advertiseAddress: 1.2.3.4 # 当前master节点的ip
13 bindPort: 6443
14 nodeRegistration:
15 criSocket: unix:///var/run/containerd/containerd.sock
16 imagePullPolicy: IfNotPresent
17 imagePullSerial: true
18 name: k8s-master01 # 对应当前的master节点名称, 如果有多个则添加多个
19 taints: null
20 timeouts:
21 controlPlaneComponentHealthCheck: 4m0s
22 discovery: 5m0s
23 etcdAPICall: 2m0s
24 kubeletHealthCheck: 4m0s
25 kubernetesAPICall: 1m0s
26 tlsBootstrap: 5m0s
27 upgradeManifests: 5m0s
28 ---
29 apiServer: {}
30 apiVersion: kubeadm.k8s.io/v1beta4
31 caCertificateValidityPeriod: 87600h0m0s
32 certificateValidityPeriod: 8760h0m0s
33 certificatesDir: /etc/kubernetes/pki
34 clusterName: kubernetes
35 controllerManager: {}
36 dns: {}
37 encryptionAlgorithm: RSA-2048
38 etcd:
39 local:
40 dataDir: /var/lib/etcd
41 imageRepository: registry.aliyuncs.com/google_containers # registry.k8s.io修改为阿里云镜像
42 kind: ClusterConfiguration
43 kubernetesVersion: 1.31.0
44 networking:
45 dnsDomain: cluster.local
46 serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16 # 这里是配置pod所在的网段, 应不与当前网络发生冲突
47 proxy: {}
48 scheduler: {}

3.3 容器镜像下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看当前版本需要的镜像, 指定版本可用kubeadm config images list --kubernetes-version=1.31.0
# kubeadm config images list
kubeadm config images list --kubernetes-version=1.31.0

# 如果下载失败, 到阿里云上下载, 下载后更改镜像名称
kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers --kubernetes-version=1.31.0



# 下载镜像
kubeadm config images pull # 实际底层使用的crictl工具下载

# 查看下载的镜像
crictl images

3.4 使用 kubeadm 初始化集群

kubeadm init –config kubeadm-config.yaml –upload-certs –v=9

如果init失败, 需要通过kubeadm reset重置操作, 并重启容器运行时sudo systemctl restart containerd

3.5 kubectl 配置

1
2
3
4
5
6
7
8
9
10
11
12
mkdir -p $HOME/.kube # 此文件夹用于存放 kubectl 的配置文件
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # 将 Kubernetes 集群初始化时生成的 admin.conf 文件复制到用户的 .kube/config 文件中
sudo chown $(id -u):$(id -g) $HOME/.kube/config # 更改文件的所有者,使其归当前用户所有

# 完成上述操作后, 查看当前节点
kubectl get nodes

# 上述命令会查看到结果: k8s-master01 NotReady control-plane 10m v1.31.0




3.6 将其余节点加入集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 在主节点上获取加入命令, 包括 IP 地址、端口、token 和 --discovery-token-ca-cert-hash 参数。
kubeadm token create --print-join-command
# 输出示例如下:
# kubeadm join 192.168.64.15:6443 --token fhgh1q.y3lit9rx5n9g42pc --discovery-token-ca-cert-hash sha256:eb8f1b9449b52c055711922ede6da56fa6606b5e1006bf4d9c0105b34498d025

# 在新节点上执行:
sudo kubeadm join 192.168.64.15:6443 --token fhgh1q.y3lit9rx5n9g42pc --discovery-token-ca-cert-hash sha256:eb8f1b9449b52c055711922ede6da56fa6606b5e1006bf4d9c0105b34498d025

# 查看节点
kubectl get nodes

# 获取 Kubernetes 集群中的组件状态 component statuses
kubectl get cs
# NAME STATUS MESSAGE ERROR
# scheduler Healthy ok
# etcd-0 Healthy ok
# controller-manager Healthy ok

4. K8S集群网络插件部署

通过上面的步骤, 集群已经初始化完成, 但是节点都还处于not ready状态, 这是是因为scheduler组件还不能完成相关的pod调度. 而这是因为sheduler缺少一些网络插件. 以下三种网络插件可以任选其一.
Flannel: 适用于小规模集群(个位数集群), 适合快速部署和简单网络需求,易于使用,但在安全性和性能上相对较弱
Calico: (10~100), 适合需要强大网络策略和安全性的应用,适合大规模部署,但配置较为复杂

Cilium: 多集群使用, 适合现代云原生应用,提供高性能和细粒度的安全策略,但对技术要求较高

本文使用Calico网络插件, Calico有两种安装方式, 一种是yaml, 一种是通过operator方式安装, 本文采用operator方式安装, 较为方便

4.1 Calico 安装

1
2
3
4
5
6
7
8
9
10
11
12
13
# 访问官网  https://docs.tigera.io/calico/3.28/about/
# 安装 Tigera Calico operator, 在master节点上操作
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/tigera-operator.yaml

# 查看calico operator是否是运行的状态, 只有是运行的状态才可进行下一步
kubectl get pods -n tigera-operator
# tigera-operator-89c775547-57prb 1/1 Running 0 54s

# 下载calico的自定义资源配置到本地
wget https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/custom-resources.yaml

# 如果无法下载, 通过浏览器访问后粘贴

修改custom-resources.yaml的第13行, 应与3.2处配置podSubnet网段保持相同

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
 1 # This section includes base Calico installation configuration.
2 # For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.Installation
3 apiVersion: operator.tigera.io/v1
4 kind: Installation
5 metadata:
6 name: default
7 spec:
8 # Configures Calico networking.
9 calicoNetwork:
10 ipPools:
11 - name: default-ipv4-ippool
12 blockSize: 26
13 cidr: 10.244.0.0/16 # 此处配置集群pod网络
14 encapsulation: VXLANCrossSubnet
15 natOutgoing: Enabled
16 nodeSelector: all()
17
18 ---
19
20 # This section configures the Calico API server.
21 # For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.APIServer
22 apiVersion: operator.tigera.io/v1
23 kind: APIServer
24 metadata:
25 name: default
26 spec: {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 应用配置
kubectl create -f custom-resources.yaml

# 查看calico pod运行情况
kubectl get pods -n calico-system -o wide
# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
# calico-kube-controllers-74cc68955d-2smdb 1/1 Running 0 15h 10.244.69.194 k8s-worker02 <none> <none>
# calico-node-h5j7d 1/1 Running 0 15h 192.168.64.17 k8s-worker02 <none> <none>
# calico-node-n9765 1/1 Running 0 15h 192.168.64.16 k8s-worker01 <none> <none>
# calico-node-xwbrm 1/1 Running 0 15h 192.168.64.15 k8s-master01 <none> <none>
# calico-typha-5d9f58495d-6nhkt 1/1 Running 0 15h 192.168.64.17 k8s-worker02 <none> <none>
# calico-typha-5d9f58495d-brgzw 1/1 Running 0 15h 192.168.64.16 k8s-worker01 <none> <none>
# csi-node-driver-f8zgg 2/2 Running 0 15h 10.244.69.193 k8s-worker02 <none> <none>
# csi-node-driver-qspfg 2/2 Running 0 15h 10.244.32.129 k8s-master01 <none> <none>
# csi-node-driver-rtrl9 2/2 Running 0 15h 10.244.79.65 k8s-worker01 <none> <none>


5. 部署应用验证K8S集群的可用性

5.1 验证Core Dns的可用性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看core DNS 服务
`kubectl get service -n kube-system`
# 结果 kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 17h

# 测试可用性
dig -t a www.baidu.com@10.96.0.10

# 如果能解析出来, 说明core DNS可用
# ;; ANSWER SECTION:
# www.baidu.com\@10.96.0.10. 1INA198.18.0.36
# 否则表示core DNS目前无法使用
# 修改如下文件, 修改DNS 服务器地址
vim /etc/resolv.conf


5.2 部署应用验证

本次使用nginx部署验证

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
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginxweb
spec:
selector:
matchLabels:
app: nginxweb
replicas: 2
template:
metadata:
labels:
app: nginxweb
spec:
containers:
- name: nginxwebc
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginxweb-service
spec:
externalTrafficPolicy: Cluster
selector:
app: nginxweb
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
type: NodePort


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 将上述yaml文件保存为nginx.yaml文件, 并使用kubectl部署
kubectl apply -f nginx.yaml
# 有如下结果表示部署成功🏅
# deployment.apps/nginxweb created
# service/nginxweb-service created

# 查看部署的pod, 这里获取到的一个nginx pod的集群ip是10.244.69.196
kubectl get pods -o wide

# 集群内访问nginx, 有nginx的页面结果, 则表示成功
curl 10.244.69.196

# 集群外访问, 使用集群任意一个节点的IP加上30080端口进行访问
# 在浏览器上访问 http://192.168.64.15:30080
# 有nginx的页面结果, 则表示部署成功🏅


6 常见问题

6.1 科学网络

开启科学上网, 下载相关的依赖时, 才更加方便

使用clash代理时, 需要开启Tun Mode

6.2 ssh操作

  • 打开ssh连接服务(慎重)
    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
    # Ubuntu 22.04
    # 安装ssh服务
    sudo apt-get install openssh-server

    # 查看sshd服务
    dpkg -l | grep ssh # openssh-server

    # 确认ssh服务是否启动
    ps -e | grep ssh
    如果看到sshd那说明ssh-server已经启动了。
    如果没有则可以这样启动:sudo /etc/init.d/ssh start或sudo service ssh start

    # 1. 编辑/etc/ssh/sshd_config文件
    PermitRootLogin yes # prohibit-password
    # PubkeyAuthentication no 千万不要这样设置!!!!, 否则主机将无法连接到重启后的虚拟机
    删除sshd_config.d中的子配置

    # 2. 重启ssh服务
    sudo /etc/init.d/ssh stop
    sudo /etc/init.d/ssh start
    sudo service ssh restart

    # 3. 安装ssh服务后,系统默认开启系统sshd,查看sshd状态如果不是默认启动,修改服务为enable
    sudo systemctl enable ssh

tips: 使用scp 命令传输文件

1
2
# 将node2上的文件cni-plugins-linux-amd64-v1.3.0.tgz复制到本地
scp root@node2:/home/ubuntu/cni-plugins-linux-amd64-v1.3.0.tgz ./

6.3 学习路径

Kubernetes学习路径

6.4 虚拟机资源准备

安装multipass, 用于准备集群所需虚拟机: brew install multipass

6.5 kubeadm kubectl kubelet 区别

kubeadm kubectl kubelet 区别

6.6 其他

kubernetes 系统各个组件调用关系:

  1. 首先要明确,一旦 kubernetes 环境启动之后,master 和 node 都会将自身的信息存储到 etcd 数据库中;
  2. 一个 nginx 服务的安装请求会首先被发送到 master 节点的 apiServer 组件;
  3. apiServer 组件会调用 scheduler 组件来决定到底应该把这个服务安装到哪个 node 节点上,在此时,它会从 etcd 中读取各个 node 节点的信息,然后按照一定的算法进行选择,并将结果告知 apiServer;
  4. apiServer 调用 controller-manager 去调度 Node 节点安装 nginx 服务;
  5. kubelet 接收到指令后,会通知 docker,然后由 docker 来启动一个 nginx 的 pod,pod 是 kubernetes 的最小操作单元,容器必须跑在 pod 中;
  6. 当Pod启动后,一个 nginx 服务就运行了,如果需要访问 nginx,就需要通过 kube-proxy 来对 pod 产生访问的代理
    这样,外界用户就可以访问集群中的 nginx 服务了

2024-08-13-Wed-T-Kubernetes搭建
http://example.com/2024/08/13/2024-08-13-Wed-T-Kubernetes搭建/
Author
Fei
Posted on
August 13, 2024
Licensed under