K8S篇-搭建kubenetes集群

news/2025/2/12 21:53:49/

安装环境

这里使用pve虚拟机搭建三台centos机器,搭建过程参考: Centos篇-Centos Minimal安装
在这里插入图片描述

此次安装硬件配置

CPU:2C
内存:2G
存储:64G

环境说明

操作系统:Centos 7.9
内核版本:6.2.0-1.el7.elrepo.x86_64
master:192.168.1.12
node1:192.168.1.13
node2:192.168.1.14
已经为三台目标机设置了ssh公钥登录,实现方式参考:Centos篇-Centos ssh公钥登录

环境准备

关闭防火墙(firewalld)和selinux

关闭防火墙指令:

systemctl stop firewalld && systemctl disable firewalld && iptables -F

firewalld和iptables是前后有两代方案,一般这俩可以先关闭,然后在部署k8s时如果确定使用iptables,可以再开启,如果使用其他方式,则firewalld和iptables均保持关闭就可以。

关闭selinux指令:

sed -i 's/enforcing/disabled/' /etc/selinux/config && setenforce 0

Selinux是内核级别的一个安全模块,通过安全上下文的方式控制应用服务的权限,是应用和操作系统之间的一道ACL,但不是所有的程序都会去适配这个模块,不适配的话开着也不起作用,何况还有规则影响到正常的服务。比如权限等等相关的问题,所以一般要关闭掉。

关闭swap分区

临时关闭指令:

swapoff -a

永久关闭指令:

sed -ri 's/.*swap.*/#&/' /etc/fstab

可以先临时关闭,再永久关闭。
Swap会导致docker的运行不正常,性能下降,是个bug,现在不知道是否有修复,但是一般关闭swap已经成了通用方案。

修改host文件

因为很多主机的名称是一样的,可能是安装时默认的,也可能是虚拟机克隆的,所以这里设置hostname来进行区分,如果像我一样在安装系统时就定义了不同的主机名,那么可以忽略。
master:

hostnamectl set-hostname centos-k8s-master.local

node1:

hostnamectl set-hostname centos-k8s-node1.local

node2:

hostnamectl set-hostname centos-k8s-node2.local

vim /etc/hosts 添加如下内容

192.168.1.12 centos-k8s-master.local
192.168.1.13 centos-k8s-node1.local
192.168.1.14 centos-k8s-node2.local

这样就可以根据主机的hostname名解析ip了。

修改内核参数

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

加载ip_vs内核模块

如果kube-proxy 模式为ip_vs则必须加载,本文采用iptables

modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack_ipv4

设置开机启动加载:

cat > /etc/modules-load.d/ip_vs.conf << EOF 
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack_ipv4
EOF

更新内核(可选)

这里我是更新了自己系统的内核,但是不是必须的,可以忽略此步骤。

启动ELRepo仓库

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm

当ELRepo仓库启用后,可以使用下面的指令列出可以使用的内核包:

yum --disablerepo="*" --enablerepo="elrepo-kernel" list available

安装内核

安装稳定版本内核:

yum --enablerepo=elrepo-kernel install kernel-ml -y 

设置默认内核

设置GRUB默认的内核版本:L;

grub2-set-default 0

重启

init 6

验证

使用下面的命令查看内核版本是否更新成功:

uname -r

新内核设置默认内核

打开并编辑/etc/default/grub并设置

GRUB_DEFAULT=0。意思是 GRUB 初始化页面的第一个内核将作为默认内核。
GRUB_TIMEOUT=5
GRUB_DEFAULT=0
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet"
GRUB_DISABLE_RECOVERY="true"

再重启完成。

安装docker

配置阿里云yum源

yum install wget -y 
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

安装指定版本docker

列出所有支持的docker版本:

yum list docker-ce.x86_64 --showduplicates |sort

选择一个版本进行安装,此处我安装的是23.0.1-1.el7

yum -y install docker-ce-23.0.1-1.el7 docker-ce-cli-23.0.1-1.el7

编辑docker配置文件

编辑/etc/docker/daemon.json

mkdir /etc/docker/ 
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://gqs7xcfd.mirror.aliyuncs.com","https://hub-mirror.c.163.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF

启动docker服务

systemctl daemon-reload && systemctl enable docker && systemctl start docker

安装kubeadm、kubelet、kubectl

配置k8s yum阿里云源

cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
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
EOF

列出kubelet指定版本

因为kubeadm、kubelet、kubectl需要安装同版本,所以一般查看kubelet就可以了,其余的使用同版本就ok

yum list kubelet --showduplicates

安装指定版本的kubeadm、kubelet、kubectl

yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6

设置kubelet开机自启

systemctl enable kubelet

部署k8s master节点

master节点初始化

kubeadm init \--kubernetes-version 1.23.6 \--apiserver-advertise-address=192.168.1.12 \--service-cidr=10.96.0.0/16 \--pod-network-cidr=10.245.0.0/16 \--image-repository registry.aliyuncs.com/google_containers 

-kubernetes-version版本一定要填与上面一致,我这里是1.23.6。
–service-cidr 指定service网络,不能和node网络冲突
–pod-network-cidr 指定pod网络,不能和node网络、service网络冲突
–image-repository registry.aliyuncs.com/google_containers 指定镜像源,由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址。

等待拉取镜像

这里可以直接使用下面的指令提前拉取镜像:

kubeadm --kubernetes-version 1.23.6 config images list

一般使用阿里云的镜像源后就慢不到哪里去了。
初始化结束后会在屏幕上出现两条重要的打印:
1、类似于initialized successfully!
2、kubeadm join xxx.xxx.xxx.xxx:6443 --token …
打印1是证明master节点初始化成功,打印2是用来加入集群的命令,在woker节点上使用,这里就不贴出来了。

配置kubectl

这里是还有三条指令,也是在初始化成功后输出的,是用来创建集群kubeconfig文件使用的命令:

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

woker节点加入集群

在各woker节点也要走一遍上面的流程走一遍(除了初始化master节点)

woker节点加入集群

使用在初始化master节点成功后输出的加入集群命令,将woker节点加入集群,我的命令是:

kubeadm join 192.168.1.12:6443 --token 37xfed.jqnw7nsll8jhdfl8 \--discovery-token-ca-cert-hash sha256:27b08986844ca2306353287507370ce7ba0caef7d4608860db4c85c762149bf6

在所有woker节点上都执行这条命令。

在master节点上查看集群节点

kubectl get nodes

差不多这个样子
在这里插入图片描述
但是我这个是已经成功运行之后的,在安装网络插件之前应该都是NotReady状态。

安装网络插件-flannel

安装 flannel

从官网下载flannel yaml文件:

wget  https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

或者直接使用我的:

apiVersion: v1
kind: Namespace
metadata:labels:k8s-app: flannelpod-security.kubernetes.io/enforce: privilegedname: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: flannelname: flannelnamespace: kube-flannel
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:labels:k8s-app: flannelname: flannel
rules:
- apiGroups:- ""resources:- podsverbs:- get
- apiGroups:- ""resources:- nodesverbs:- get- list- watch
- apiGroups:- ""resources:- nodes/statusverbs:- patch
- apiGroups:- networking.k8s.ioresources:- clustercidrsverbs:- list- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:labels:k8s-app: flannelname: flannel
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: flannel
subjects:
- kind: ServiceAccountname: flannelnamespace: kube-flannel
---
apiVersion: v1
data:cni-conf.json: |{"name": "cbr0","cniVersion": "0.3.1","plugins": [{"type": "flannel","delegate": {"hairpinMode": true,"isDefaultGateway": true}},{"type": "portmap","capabilities": {"portMappings": true}}]}net-conf.json: |{"Network": "10.245.0.0/16","Backend": {"Type": "vxlan"}}
kind: ConfigMap
metadata:labels:app: flannelk8s-app: flanneltier: nodename: kube-flannel-cfgnamespace: kube-flannel
---
apiVersion: apps/v1
kind: DaemonSet
metadata:labels:app: flannelk8s-app: flanneltier: nodename: kube-flannel-dsnamespace: kube-flannel
spec:selector:matchLabels:app: flannelk8s-app: flanneltemplate:metadata:labels:app: flannelk8s-app: flanneltier: nodespec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/osoperator: Invalues:- linuxcontainers:- args:- --ip-masq- --kube-subnet-mgrcommand:- /opt/bin/flanneldenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespace- name: EVENT_QUEUE_DEPTHvalue: "5000"image: docker.io/flannel/flannel:v0.21.2name: kube-flannelresources:requests:cpu: 100mmemory: 50MisecurityContext:capabilities:add:- NET_ADMIN- NET_RAWprivileged: falsevolumeMounts:- mountPath: /run/flannelname: run- mountPath: /etc/kube-flannel/name: flannel-cfg- mountPath: /run/xtables.lockname: xtables-lockhostNetwork: trueinitContainers:- args:- -f- /flannel- /opt/cni/bin/flannelcommand:- cpimage: docker.io/flannel/flannel-cni-plugin:v1.1.2name: install-cni-pluginvolumeMounts:- mountPath: /opt/cni/binname: cni-plugin- args:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistcommand:- cpimage: docker.io/flannel/flannel:v0.21.2name: install-cnivolumeMounts:- mountPath: /etc/cni/net.dname: cni- mountPath: /etc/kube-flannel/name: flannel-cfgpriorityClassName: system-node-criticalserviceAccountName: flanneltolerations:- effect: NoScheduleoperator: Existsvolumes:- hostPath:path: /run/flannelname: run- hostPath:path: /opt/cni/binname: cni-plugin- hostPath:path: /etc/cni/net.dname: cni- configMap:name: kube-flannel-cfgname: flannel-cfg- hostPath:path: /run/xtables.locktype: FileOrCreatename: xtables-lock

官网下载的yaml文件需要注意:net-conf.json内部的Network要与初始化master节点的pod-network-cidr保持一致。
官网默认下载的是:10.244.0.0/16
我修改为了:10.245.0.0/16

执行yaml文件:

kubectl apply -f kube-flannel.yaml

查看flannel部署结果

kubectl -n kube-system get pods -o wide

在这里插入图片描述
等待flannel节点ready。

查看各个woker节点的状态

等flanner部署成功后,应该所有节点都ready了。
在这里插入图片描述

修改kube-proxy的模式为iptables

如果centos的内核高于4,则可以忽略:

kubectl get cm kube-proxy -n kube-system -o yaml | sed 's/mode: ""/mode: "iptables"/' | kubectl apply -f -
kubectl -n kube-system rollout restart  daemonsets.apps  kube-proxy
kubectl -n kube-system rollout restart  daemonsets.apps  kube-flannel-ds

部署metrics-server

部署metrics-server

metrics-server.yaml

apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: metrics-servername: metrics-servernamespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:labels:k8s-app: metrics-serverrbac.authorization.k8s.io/aggregate-to-admin: "true"rbac.authorization.k8s.io/aggregate-to-edit: "true"rbac.authorization.k8s.io/aggregate-to-view: "true"name: system:aggregated-metrics-reader
rules:
- apiGroups:- metrics.k8s.ioresources:- pods- nodesverbs:- get- list- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:labels:k8s-app: metrics-servername: system:metrics-server
rules:
- apiGroups:- ""resources:- pods- nodes- nodes/stats- namespaces- configmapsverbs:- get- list- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:labels:k8s-app: metrics-servername: metrics-server-auth-readernamespace: kube-system
roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccountname: metrics-servernamespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:labels:k8s-app: metrics-servername: metrics-server:system:auth-delegator
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: system:auth-delegator
subjects:
- kind: ServiceAccountname: metrics-servernamespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:labels:k8s-app: metrics-servername: system:metrics-server
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: system:metrics-server
subjects:
- kind: ServiceAccountname: metrics-servernamespace: kube-system
---
apiVersion: v1
kind: Service
metadata:labels:k8s-app: metrics-servername: metrics-servernamespace: kube-system
spec:ports:- name: httpsport: 443protocol: TCPtargetPort: httpsselector:k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:labels:k8s-app: metrics-servername: metrics-servernamespace: kube-system
spec:replicas: 1selector:matchLabels:k8s-app: metrics-serverstrategy:rollingUpdate:maxUnavailable: 0template:metadata:labels:k8s-app: metrics-serverspec:containers:- args:- --cert-dir=/tmp- --secure-port=443- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname- --kubelet-use-node-status-port- --metric-resolution=15s# 跳过tls,解决cannot validate certificate for 192.168.65.3 because it doesn’t contain any IP SANs报错- --kubelet-insecure-tlsimage: k8s.gcr.io/metrics-server/metrics-server:v0.5.0imagePullPolicy: IfNotPresentlivenessProbe:failureThreshold: 3httpGet:path: /livezport: httpsscheme: HTTPSperiodSeconds: 10name: metrics-serverports:- containerPort: 443name: httpsprotocol: TCPreadinessProbe:failureThreshold: 3httpGet:path: /readyzport: httpsscheme: HTTPSinitialDelaySeconds: 20periodSeconds: 10resources:requests:cpu: 100mmemory: 200MisecurityContext:readOnlyRootFilesystem: truerunAsNonRoot: truerunAsUser: 1000volumeMounts:- mountPath: /tmpname: tmp-dir- mountPath: /etc/localtimename: host-timenodeSelector:kubernetes.io/os: linuxpriorityClassName: system-cluster-criticalserviceAccountName: metrics-servervolumes:- emptyDir: {}name: tmp-dir- name: host-timehostPath:path: /etc/localtime---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:labels:k8s-app: metrics-servername: v1beta1.metrics.k8s.io
spec:group: metrics.k8s.iogroupPriorityMinimum: 100insecureSkipTLSVerify: trueservice:name: metrics-servernamespace: kube-systemversion: v1beta1versionPriority: 100metrics-server

命令:

kubectl apply -f metrics-server.yaml

http://www.ppmy.cn/news/27658.html

相关文章

Hive---分区表和分桶表

分区表和分桶表 文章目录分区表和分桶表分区表语法加载数据增加分区删除分区查看分区表有多少分区查看分区表结构动态分区开启动态分区功能&#xff08;默认 true&#xff0c;开启&#xff09;设置为非严格模式在所有执行 MR 的节点上&#xff0c;最大一共可以创建多少个动态分…

一文深入分析-内核并发消杀器(KCSAN)

一、KCSAN介绍 KCSAN(Kernel Concurrency Sanitizer)是一种动态竞态检测器&#xff0c;它依赖于编译时插装&#xff0c;并使用基于观察点的采样方法来检测竞态&#xff0c;其主要目的是检测数据竞争。 KCSAN是一种检测LKMM(Linux内核内存一致性模型)定义的数据竞争(data race…

电脑技巧:分享六个非常实用的资源网站

今天小编给大家分享六个非常实用的资源网站&#xff0c;大家一起来看看吧&#xff01; 1、高清壁纸&#xff1a;Wallhaven 一个免费的高清壁纸下载网站&#xff0c;里面的壁纸资源丰富&#xff0c;更新速度也快&#xff0c;各种类型的壁纸都能找到&#xff0c;尤其是动漫壁纸。…

【C#基础】C# 面向对象编程

序号系列文章5【C#基础】C# 运算符总结6【C#基础】C# 常用语句讲解7【C#基础】C# 常用数据结构文章目录前言面向对象的 C#1&#xff0c;类的概念2&#xff0c;类的定义3&#xff0c;类成员4&#xff0c;对象5&#xff0c;继承6&#xff0c;多态性结语前言 &#x1f60a;大家好&…

Python编程自动化办公案例(3)

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.前几章代码 1.获取到第一题的选项单元格 2.实现批量获取文件 二. 批…

通过cfssl自签证书https证书

背景 公司内部自建Web服务&#xff0c;通过自签CA&#xff0c;然后签发https证书 工具地址: GitHub - cloudflare/cfssl: CFSSL: Cloudflares PKI and TLS toolkit 使用步骤: 1. 在release页面中下载最新的二进制包&#xff0c;我使用的是1.5的解压并重命名二进制文件 tar…

【手撕源码】vue2.x双向数据绑定原理

&#x1f431; 个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域新星创作者、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab;系列专栏&#xff1a;vue3从入门…

CSS 网页动画【快速掌握知识点】

目录 前言 一、使用CSS3动画 二、使用CSS过渡 三、使用CSS变换&#xff1a; 前言 CSS是一种用于网页设计和排版的语言&#xff0c;也可以用它来制作网页动画。 一、使用CSS3动画 CSS3引入了动画属性&#xff0c;允许您为元素设置动画效果。您可以使用关键帧来定义动画的开始…