0%

kubernetes集群部署

前言

Kubernetes,简称K8s,是一个开源的容器编排平台,用于自动化应用程序的部署、扩展和管理。本文我们来搭建一个简单的kubernetes集群。

基本环境准备

(1)我们这次搭建的环境包括4个节点,1个master节点和3个worker节点,每台虚拟机的资源为:2core、4G内存、50G硬盘;虚拟机安装的镜像为:CentOS-7-x86_64-Minimal-2009.iso

(2)为虚拟机设置静态IP,我设置4台机器的ip为

1
2
3
4
192.168.218.131
192.168.218.132
192.168.218.133
192.168.218.134

(3)为虚拟机设置主机名,我设置4台机器的主机名为

1
2
3
4
192.168.218.131	k8s-master
192.168.218.132 k8s-worker1
192.168.218.133 k8s-worker2
192.168.218.134 k8s-worker3

(4)设置虚拟机的hosts,使虚拟机可以利用主机名互相访问

1
2
3
4
5
6
7
8
# 进入hosts文件
sudo vi /etc/hosts

# 将ip和主机名对应关系添加到末尾
192.168.218.131 k8s-master
192.168.218.132 k8s-worker1
192.168.218.133 k8s-worker2
192.168.218.134 k8s-worker3

(5)关闭linux安全模块selinux

(6)关闭系统交换分区(swap area)

(7)关闭防火墙

(8)将桥接网络的IPv4流量转发到iptables

(9)设置三台虚拟机的时间同步并设置时区

镜像工具安装

1. 安装docker

(1)参考‘虚拟机的初始准备’-‘安装基础软件’-‘安装docker’,这里安装的版本是:20.10.24
(2)修改docker的cgroup 驱动
1
2
3
4
5
6
7
8
9
# 编辑文件‘/etc/docker/daemon.json’,添加如下内容
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}

​ 保存文件后,重启 Docker 服务以应用更改

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

​ 确认 Docker 已切换到 systemd

1
2
# 应该输出:Cgroup Driver: systemd
docker info | grep -i cgroup

2. 安装kubeadm、kubelet、kubectl

  • Kubeadm 是一个快捷搭建kubernetes(k8s)的安装工具,它提供了 kubeadm init 以及 kubeadm join 这两个命令来快速创建 kubernetes 集群,kubeadm 通过执行必要的操作来启动和运行一个最小可用的集群

  • Kubelet 是 kubernetes 工作节点上的一个代理组件,运行在每个节点上

  • kubectl是Kubernetes集群的命令行工具,通过kubectl能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署

(1)修改yum的kubernetes镜像源
1
2
# 编辑该文件
vi /etc/yum.repos.d/kubernetes.repo
1
2
3
4
5
6
7
8
9
# 在文件中添加如下内容,我们这里使用阿里云的镜像源
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kube*
1
2
3
# 清理并更新缓存
sudo yum clean all
sudo yum makecache
(2)使用yum安装
1
2
3
# --disableexcludes=kubernetes  只能使用kubernetes仓库(我们上一步设置的仓库)
sudo yum -y install kubelet-1.21.0-0 kubeadm-1.21.0-0 kubectl-1.21.0-0 \
--disableexcludes=kubernetes
(3)启动服务、设置开机自启、查看服务状态
1
2
3
4
# kubelet
sudo systemctl status kubelet
sudo systemctl start kubelet
sudo systemctl enable kubelet

初始化kubernetes节点

1. 初始化master节点

(1)初始化
1
2
3
4
5
6
7
8
9
10
11
12
# 查看kubeadm有哪些版本可用
yum list --showduplicates kubeadm --disableexcludes=kubernetes

# 初始化
# --image-repository registry.aliyuncs.com/google_containers:使用阿里云镜像源
# --kubernetes-version=v1.21.0:指定k8s的版本
# --pod-network-cidr=192.168.254.0/24: 指定pod的网段
# 我们第一次使用这个命令不会初始化成功,因为阿里云镜像源中缺乏一个coredns镜像
kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.21.0 \
--pod-network-cidr=192.168.254.0/24

​ - 注:pod的概念类似docker-compose中的一个docker-compose.yml文件所管理的容器;一个docker-compose.yml文件启动的容器会共享一些资源,如网络、存储卷、环境变量等;这里的网段为什么是‘192.168.254.0/24’,因为calico默认的网段是‘192.168.0.0’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 如果初始化成功,我们会看到这样一段信息:
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 192.168.218.131:6443 --token 3679yv.0vxbxqragunypp8y \
--discovery-token-ca-cert-hash sha256:0ec8eafa7ecdcb439e503ea2a07c67b4479774b1c7a6c86423710e230fcc5c67

​ 我们可以根据提示信息创建目录和配置文件

1
2
3
4
5
mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config

​ 使用如下命令查看节点

1
kubectl get node

​ 如果之前的操作都没问题,我们已经可以看到master节点了

image-20250221130340219

(2)可能出现的问题

​ a. 阿里云镜像源中没有coredns镜像

1
2
3
4
5
6
7
# 手动拉取coredns镜像
docker pull coredns/coredns:v1.8.0
# 将这个镜像重命名,否则k8s无法识别
docker tag coredns/coredns:1.8.0 registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0
# 查看是否重命名成功
docker images
#(看到'registry.aliyuncs.com/google_containers/coredns/coredns v1.8.0'

​ b. 报错信息:WARNING IsDockerSystemdCheck]: detected “cgroupfs” as the Docker cgroup driver. The recommended driver is “systemd”. Please follow the guide at https://kubernetes.io/docs/setup/cri/;这是需要修改docker的cgroup 驱动

2. 添加worker节点

​ 上一条目中初始化master成功,输出的命令中有信息

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

kubeadm join 192.168.218.131:6443 --token 3679yv.0vxbxqragunypp8y \
--discovery-token-ca-cert-hash sha256:0ec8eafa7ecdcb439e503ea2a07c67b4479774b1c7a6c86423710e230fcc5c67

​ 我们可以根据该命令将worker节点添加到集群中,但是需要保证worker节点虚拟机已经正确安装了docker、kubelet、kubectl,并且这些服务已经正确启动;

1
2
sudo systemctl status docker
sudo systemctl status kubelet

​ worker节点添加成功会显示如下信息

1
2
3
4
5
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

​ 根据提示信息,在master节点使用如下命令来查看添加的worker节点

1
2
# 不做配置,这个命令默认在master节点生效
kubectl get nodes

​ 如果忘记了添加worker节点的命令,可以在master节点用如下命令获取

1
kubeadm token create --print-join-command

部署CNI网络插件calico

虽然现在k8s集群已经有1个master节点,2个worker节点,但是此时三个节点的状态都是NotReady的,原因是没有CNI网络插件,为了节点间的通信,需要安装cni网络插件,常用的cni网络插件有calico和flannel,两者区别为:flannel不支持复杂的网络策略,calico支持网络策略,因为今后还要配置k8s网络策略networkpolicy,所以本文选用的cni网络插件为calico

  • 注:calico只需要在master部署

1.去官网下载calico.yaml文件

官网:https://projectcalico.docs.tigera.io/about/about-calico

image-20250221181457495

搜索框里搜索calico.yaml,找到下载链接

image-20250221183049204

1
2
# 下载链接
curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/calico.yaml -O

2.下载镜像

​ 下载后我们可以看看calico.yaml文件中有哪些需要下载的镜像,使用命令‘grep image calico.yaml’

image-20250221202935457

calico.yaml中过滤出的镜像名称
1
2
3
4
5
6
7
8
9
# 排除重复和无效内容,还有如下三个镜像
image: docker.io/calico/cni:v3.29.2
image: docker.io/calico/node:v3.29.2
image: docker.io/calico/kube-controllers:v3.29.2

# 手动拉取
docker pull docker.io/calico/cni:v3.29.2
docker pull docker.io/calico/node:v3.29.2
docker pull docker.io/calico/kube-controllers:v3.29.2

3.修改calico.yaml文件中的配置信息

​ 修改calico.yaml文件中的CALICO_IPV4POOL_CIDR项,将其修改为初始化master节点时设置的pod网段

1
2
3
# 打开注释
- name: CALICO_IPV4POOL_CIDR
value: "192.168.254.0/24"

​ 使用命令查看calico.yaml是否正确修改了

1
cat calico.yaml | egrep "CALICO_IPV4POOL_CIDR|"192.168""

image-20250221210728581

calico.yaml文件中被修改的内容

​ 使用kubectl加载calico.yaml

1
kubectl apply -f calico.yaml

​ 我们再使用命令查看节点状态,可以看到节点状态现在变成‘ready’了

1
kubectl get nodes

image-20250221213907397

可以看到所有节点的状态都已经为‘Ready’

kubernetes的相关概念

namespace(命名空间)

  • 作用:Namespace 是 Kubernetes 中用于资源隔离的逻辑分区。它可以将集群资源划分为多个虚拟集群,每个 Namespace 中的资源名称可以重复,但在不同 Namespace 之间是隔离的。
  • 使用场景
    • 将不同团队或项目的资源隔离开。
    • 管理不同环境(如开发、测试、生产)的资源。
  • 示例
1
2
3
4
apiVersion: v1
kind: Namespace
metadata:
name: my-namespace

ConfigMap(配置映射)

  • 作用:ConfigMap 用于将非敏感配置数据(如环境变量、配置文件)与容器镜像解耦,使应用程序的配置更加灵活。

  • 使用场景

    • 存储应用程序的配置文件(如 JSON、YAML)。

    • 注入环境变量到容器中。

  • 示例

1
2
3
4
5
6
7
8
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
app.properties: |
key1=value1
key2=value2

Service(服务,定义访问策略)

  • 作用:Service 用于定义一组 Pod 的访问策略,提供稳定的网络端点(IP 和端口),使外部或其他服务可以访问这些 Pod。
  • 使用场景
    • 暴露应用程序给集群内部或外部访问。
    • 负载均衡多个 Pod 的流量。
  • 类型:
    • ClusterIP:默认类型,仅在集群内部访问。
    • NodePort:通过节点 IP 和端口暴露服务。
    • LoadBalancer:通过云提供商的负载均衡器暴露服务。
  • 示例
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP

StatefulSet(有状态应用集,部署有状态服务)

  • 作用:StatefulSet 用于管理有状态应用程序(如数据库、消息队列),确保 Pod 具有唯一的网络标识和持久化存储。
  • 特点
    • Pod 按顺序创建和删除。
    • 每个 Pod 有唯一的名称和稳定的网络标识(如 pod-0, pod-1)。
    • 支持持久化存储(PersistentVolume)。
  • 使用场景
    • 运行需要稳定网络标识和存储的应用,如 MySQL、Kafka 等。
  • 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-statefulset
spec:
serviceName: "my-service"
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image

Deployment(部署无状态服务)

  • 作用:Deployment 用于管理无状态应用程序,支持滚动更新、回滚和 Pod 的自动扩缩容。
  • 特点
    • 定义 Pod 的副本数和更新策略。
    • 支持声明式更新(通过修改 YAML 文件)。
    • 自动管理 ReplicaSet,确保 Pod 数量符合预期。
  • 使用场景
    • 部署无状态应用,如 Web 服务、API 服务。
  • 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image

PersistentVolume (PV)

  • 定义:PersistentVolume (PV) 是集群中的一块存储资源,由管理员预先配置。它可以是物理存储(如本地磁盘)或网络存储(如 NFS、AWS EBS、GCP Persistent Disk 等)

  • 特点

    • 独立于 Pod:PV 的生命周期与 Pod 无关,即使 Pod 被删除,PV 仍然存在。
    • 静态配置:通常由管理员手动创建,定义存储的大小、访问模式、回收策略等。
    • 动态配置:也可以通过 StorageClass 动态创建 PV。
    • 访问模式
      • ReadWriteOnce (RWO):可被单个节点挂载为读写模式。
      • ReadOnlyMany (ROX):可被多个节点挂载为只读模式。
      • ReadWriteMany (RWX):可被多个节点挂载为读写模式。
    • 回收策略
      • Retain:PV 被释放后保留数据,需要手动清理。
      • Delete:PV 被释放后自动删除底层存储。
      • Recycle(已弃用):PV 被释放后自动清理数据。
  • 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
namespace: my-namespace
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 10.198.1.155
path: "/data/nfs"

PersistentVolumeClaim (PVC)

  • 定义:PersistentVolumeClaim (PVC) 是用户对存储资源的请求。它类似于 Pod 对 CPU 和内存的请求,用户通过 PVC 申请特定大小和访问模式的存储资源。
  • 特点
    • 动态绑定:PVC 会自动绑定到符合条件的 PV。
    • 解耦存储和 Pod:Pod 通过 PVC 使用存储,而无需关心具体的 PV 实现。
    • 资源请求:可以指定存储大小和访问模式。
    • 生命周期:PVC 的生命周期通常与 Pod 绑定,但可以独立于 Pod 存在。
  • 示例
1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs

kubectl的一些常用操作

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
# 使用yaml文件创建资源
kubectl apply -f <filename.yaml>

# 查看所有namespace
kubectl get namespace
# 创建一个namespace
kubectl create namespace <namespace>
# 查看某个namespace的详细信息
kubectl describe namespace <namespace>
# 删除某个namespace
kubectl delete namespace <namespace>

# 查看configmap
kubectl get configmap -n <namespace>

# 查看Deployment
kubectl get deployment -n <namespace>
# 停止 Deployment (将容器数量缩减至0)
kubectl scale deployment <deployment-name> --replicas=0 -n <namespace>
# 删除 Deployment
kubectl delete deployment <deployment-name> -n mysql

# 查看statefulset
kubectl get statefulset -n <namespace>
# 停止statefulset (将容器数量缩减至0)
kubectl scale statefulset <statefulset-name> --replicas=0 -n <namespace>

# 查看Pod
kubectl get pod -n <namespace>
# 删除Pod
kubectl delete pod <pod-name> -n <namespace>
# 进入pod(mysql)
kubectl exec -it <pod-name> -- mysql -uroot -ppassword
# 查看pod日志
kubectl logs <pod-name> -n mysql -c <container-name>
# 检查pod的控制器
kubectl get pod <pod-name> -n mysql -o yaml

# 查看pv
kubectl get pv
# 删除pv
kubectl delete pv <pv-name>

# 查看pvc
kubectl get pvc -n <namespace>
# 删除pvc
kubectl delete pvc <pvc-name> -n <namespace>