前言 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 
	使用如下命令查看节点
	如果之前的操作都没问题,我们已经可以看到master节点了
(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 
1.去官网下载calico.yaml文件 官网:https://projectcalico.docs.tigera.io/about/about-calico 
搜索框里搜索calico.yaml,找到下载链接
1 2 #  下载链接 curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/calico.yaml -O 
2.下载镜像 	下载后我们可以看看calico.yaml文件中有哪些需要下载的镜像,使用命令‘grep image calico.yaml’
	
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"" 
calico.yaml文件中被修改的内容 
	使用kubectl加载calico.yaml
1 kubectl apply -f calico.yaml 
	我们再使用命令查看节点状态,可以看到节点状态现在变成‘ready’了
	
可以看到所有节点的状态都已经为‘Ready’ 
kubernetes的相关概念 namespace(命名空间) 
作用 :Namespace 是 Kubernetes 中用于资源隔离的逻辑分区。它可以将集群资源划分为多个虚拟集群,每个 Namespace 中的资源名称可以重复,但在不同 Namespace 之间是隔离的。使用场景 :
将不同团队或项目的资源隔离开。 
管理不同环境(如开发、测试、生产)的资源。 
 
示例 : 
1 2 3 4 apiVersion:  v1 kind:  Namespace metadata:   name:  my-namespace  
ConfigMap(配置映射) 
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 数量符合预期。 
 
使用场景 :
示例 : 
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) 
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>