k8s学习笔记

一、概念

1. 定义

k8s是Google开源的一个容器集群管理系统。

k8s用于容器化应用程序部署、扩展和管理。

k8s提供了容器编排,资源调度,自动修复,弹性伸缩(自动根据服务器的并发情况扩增或者缩减容器数量),自动部署,回滚处理,服务发现,负载均衡等一些列功能。

k8s目标是让容器化应用简单高效。

官网:https://kubernetes.io

官方中文文档:https://kubernetes.io/zh/docs/home

简单理解:仅用 Docker,则只能管理单个服务器节点的容器,而无法同时维护多个服务器节点。通过使用k8s则可以使用同一入口即可同时维护多个服务器节点的所有容器,并可以实现多服务器之间的自动修复,弹性伸缩,回滚处理,服务发现,负载均衡等。

2. 核心对象

Kubernetes 对象

  • Pod

    • 最小可部署单元(k8s不能直接启动容器,而是需要通过Pod间接启动容器)
    • 一组容器(docker)集合
    • 一个Pod中的所有容器共享网络命名空间
    • Pod是短暂的,运行完就结束了
  • Service 服务

    • 将一组Pod(比如mysql Pod)关联起来,提供统一的入口
    • 防止pod失联,Pod地址发生改变,入口不受影响
  • Volume 数据卷

  • Namespace 命名空间

    • 用于隔离Pod的运行环境(默认情况Pod可以互相访问)
    • 使用场景:
      • ①为开发环境、测试环境、生产环境准备不同的命名空间
    • ②为不同的用户提供不同的隔离的运行环境
  • Controller 控制器

    Controller控制器基本对象构建并提供额外的功能和方便使用的特性,用于控制pod启动、停止、删除等。

3. 节点分类和重要组件

  • master node:主控节点

  • worker node:工作节点

(1)master node 相关的组件(程序)

  • apiserver:接收客户端操作k8s的指令(唯一入口),此外也是其他组件互调的桥梁。提供认证、授权、访问控制、API 注册和发现等机制。
  • schduler:负责资源调度,根据规定的调度策略,在多个worker node服务器的pod中选举一个来部署容器。
  • controller manager:管理控制器,负责维护技巧的状态,包括故障检测、自动扩展、滚动更新等,以及用于向work node的kubelet发送指令。
  • etcd:分布式键值对数据库。用于保存整个集群的状态数据,比如pod、service等对象信息。

(2)worker node 相关的组件(程序)

  • kubelet:向容器发送指令以管理容器,同时负责 Volume(CVI)和网络(CNI)的管理。并汇报节点状态给apiserver,再保存状态至etcd。
  • kubeproxy:管理docker容器的网络(包括服务发现与负载均衡等,主要提供 iptables、ipvs 规则)。

Components of Kubernetes

二、部署 k8s 集群

1. 集群规划

主机名ip组件
k8s-master192.168.60.101kube-apiserver、kube-controller-manager、kube-scheduler、etcd
k8s-node1192.168.60.201kubelet、kube-proxy
k8s-node2192.168.60.202kubelet、kube-proxy

2. 系统环境

  • 操作系统:centos7
  • k8s版本:1.23.6
  • docker版本:18.09.9-3
  • 硬件配置:至少2G内存,2核CPU

3. 初始化服务器

(1)关闭防火墙

1
2
systemctl stop firewalld
systemctl disable firewalld

如为云服务器,则需要注意开放相关安全组端口:

  • master 节点:TCP至少开放:6443、2379、2380、60080、60081;UDP协议端口全开
  • worker 节点:UDP协议端口全开

(2)关闭selinux

1
2
3
4
5
6
7
# 临时生效
setenforce 0
# 永久生效(推荐)
sed -i 's/enforcing/disabled/' /etc/selinux/config

# 重启以生效
reboot

(3)关闭交换分区

1
2
3
4
5
6
7
8
9
10
11
# 临时生效
swapoff -a

# 永久生效(注释掉swap的配置)
sed -ri 's/.*swap.*/#&/' /etc/fstab

# 重启以生效
reboot

#检测是否关闭成功(total为0即可)
free -m

(4)配置主机名

1
2
3
4
5
6
7
8
9
10
#在k8s-master上执行
hostnamectl set-hostname k8s-master
#在k8s-node1上执行
hostnamectl set-hostname k8s-node1
#在k8s-node2上执行
hostnamectl set-hostname k8s-node2


#查看主机名(验证是否修改成功)
hostname

(5)配置名称解析

三台主机都做如下配置

1
2
3
4
5
cat << EOF >> /etc/hosts
192.168.60.101 k8s-master
192.168.60.201 k8s-node1
192.168.60.202 k8s-node2
EOF

然后互相ping查看是否都能通过主机名连接

1
2
$ ping 主机名
#如:ping k8s-master

(6)修改内核参数(开启数据包转发功能)

所有服务器都执行如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
#vm.swappiness = 0
#vm.max_map_count = 262144
EOF

# 加载br_netfilter模块
# 查看是否加载:lsmod | grep br_netfilter
modprobe br_netfilter

# 使配置生效
sysctl -p /etc/sysctl.d/k8s.conf

(7)配置时间同步

所有服务器都执行如下命令以同步时间:

1
2
3
4
yum install ntpdate -y
#强制快速同步系统时间
ntpdate ntp1.aliyun.com
hwclock -w

(8)安装 ipset 和 ipvsadm

所有服务器都执行如下命令:

在kubernetes中service有两种代理模型,一种是基于iptables,另一种是基于ipvs的。ipvs的性能要高于iptables的,但是如果要使用它,需要手动载入ipvs模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装
yum install -y ipset ipvsadm

# 配置
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF

# 授权、运行、检查是否加载:
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4

4. 安装 Docker

所有服务器都执行如下命令:

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
#安裝Docker源
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
#查看可安装的docker版本
yum list docker-ce --showduplicates
#选择指定版本Docker安装
yum install -y --setopt=obsoletes=0 docker-ce-18.06.3.ce-3.el7


#启动Docker
systemctl start docker
systemctl enable docker


#配置Docker加速源,并修改cgroup驱动为k8s官方推荐的systemd,否则k8s初始化可能会报错
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF


#重启 docker 服务
systemctl restart docker
#查看 Docker 配置是否修改生效(关注:Registry Mirrors、Cgroup Driver)
docker info

注意:K8s 和 Docker 之间有一些版本兼容性要求,以确保它们可以正常协作工作

5. 安裝 k8s 相关工具

所有服务器都执行如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#添加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=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF


#安装kubeadm、kubelet、kubectl
yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6

# 为了实现Docker使用的cgroup drvier和kubelet使用的cgroup drver一致,需要修改"/etc/sysconfig/kubelet"文件的内容:
cat > /etc/sysconfig/kubelet <<EOF
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
KUBE_PROXY_MODE="ipvs"
EOF

#设置kubelet开机自启动
systemctl enable kubelet

6. 初始化 Master 节点

在 Master 节点上执行:

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
#初始化k8s集群(自动运行必要组件到Docker容器中)
#apiserver-advertise-address填写当前Master节点的实际ip,其他地方不用动
#image-repository:指定拉取镜像的地址(由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里需要指定阿里云镜像仓库地址)
#service-cidr:k8s服务发现网段
#pod-network-cidr:Pod运行的网段
kubeadm init \
--apiserver-advertise-address=192.168.60.101 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.23.6 \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.2.0.0/16 \
--service-dns-domain=cluster.local \
--ignore-preflight-errors=Swap \
--ignore-preflight-errors=NumCPU \
--ignore-preflight-errors=Mem



# 配置环境变量和配置文件
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config


#echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
#source ~/.bash_profile

7. 初始化 Node 节点

1
2
3
4
5
6
7
8
9
10
11
12
13
#在Master节点获取token(在Master执行)
kubeadm token create --print-join-command --ttl 0

##在Node执行如下命令
# 在node1和node2添加如下的命令向k8s集群中添加Node节点(根据Master节点获取token将当前Node节点加入到集群中):
kubeadm join 192.168.60.101:6443 --token pikadq.zwpr1wpypqp71ssk --discovery-token-ca-cert-hash sha256:eaa3781137e6180b0a23d670335614f13b5b93f6f1ce5b0696a6fe930aef890c


##在Master执行如下命令
# 获取所有节点(正常可以获取到master,node1和node2)
kubectl get nodes
# 获取所有节点(含更多详细信息)
kubectl get nodes -owide

其他相关 token 令牌的命令:

1
2
3
4
5
6
7
8
#列出当前有效的token令牌列表
kubeadm token list

#获取证书公钥hash值
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

#Node加入集群的命令
kubeadm join <master节点的IP>:6443 --token <有效的token令牌> --discovery-token-ca-cert-hash sha256:<证书公钥hash值>

8. 部署 CNI 网络插件

在 Master 节点部署CNI网络插件:

1
2
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#代理下载:wget https://gh.con.sh/https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
1
2
3
4
#修改flannel配置文件
vim kube-flannel.yml
#(1)修改 "Network": "10.244.0.0/16" 的值为初始化集群时pod-network-cidr的网段,即:10.2.0.0/16
#(2)在kube-flannel容器中添加一行参数:- --iface=ens33 (其中ens33为Master节点的网卡名称)

具体修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  net-conf.json: |
{
"Network": "10.2.0.0/16", #(1)修改Pod网段
"Backend": {
"Type": "vxlan"
}
}

#其他配置内容
containers:
- name: kube-flannel
image: docker.io/flannel/flannel:v0.22.3
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens33 #(2)添加网卡名称(其中ens33为Master节点的网卡名称)
1
2
3
4
5
6
7
8
9
10
11
12
13
kubectl apply -f kube-flannel.yml
#查看pode的状态(查看部署进度,等所有Pod状态都变成Running,需要耐心等待一下),
kubectl get pods -n kube-system
#获取所有节点(等待所有节点状态都为Ready)
kubectl get nodes -owide
#查看集群健康状态
kubectl get cs

#所有节点状态都为Ready,并且所有Pod状态都变成Running时说明集群部署完成
#kube-controller-manager和kube-scheduler-k8s状态如果为CrashLoopBackOff,通常是Master节点分配的资源太少造成的,建议给Master节点分配多一点资源,至少2G内存,2核CUP,然后重启即可

#查看指定Pod的详细信息(包括Pod的状态、容器的状态、事件日志等)
#kubectl describe pods kube-controller-manager-k8s-master -n kube-system

9. 通过 k8s 启动 nginx 容器

待 k8s 集群部署好后,就可以在集群中运行容器了。在master节点上执行操作:

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
#创建Pod控制器(通过部署间接创建容器)
#在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod
#Pod控制器的种类有很多,如:Deployment、ReplicaSet、StatefulSet、DaemonSet、Job、CronJob等
#在集群中创建一个名为 "nginx-test" 的Pod控制器(Deployment)
#k8s会随机选择node节点进行镜像下载和启动
#nginx-test 为docker服务名称,可以自定义名称
#--replicas 指定创建的Pod副本数
#--image 指定要使用的docker镜像版本
kubectl create deployment nginx-test --replicas=3 --image=nginx:1.8


#列出所有Deployment类型的Pod控制器
kubectl get deployment
#查看pode的状态(含部署服务)
kubectl get pods -owide

#给Pod控制器创建服务(简单理解:即暴露容器的端口给宿主机)
kubectl expose deployment nginx-test --type=NodePort --port=80

#列出集群中的所有服务
#服务:服务与Pod控制器相关,表示向客户端提供访问Pod的接口,提供有负载均衡和服务发现的能力。
#简写:kubectl get svc
kubectl get services
#NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
#kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 60m
#nginx-test NodePort 10.1.6.232 <none> 80:32724/TCP 6s


#比如通过上面的命令查nginx容器映射到宿主机端口是32724,那么访问集群任意一个节点()的32724端口都能访问nginx
curl http://192.168.60.101:32724
curl http://192.168.60.201:32724


#删除Pod控制器(如需)
kubectl delete deployment nginx-test
#删除服务(如需)
kubectl delete service nginx-test

#修改指定Pod控制器的副本数(如需)
kubectl scale deployment --replicas=2 nginx-test

#执行Pod容器命令
kubectl exec nginx-test-7cf98b694b-6p6xg -- ls /
#进入Pod容器执行命令
kubectl exec -it nginx-test-7cf98b694b-6p6xg -- bash

10. 部署 Dashboard

在 Matser 上执行下面操作安装 Dashboard

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
#下载yaml配置文件
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml
#代理下载:wget https://gh.con.sh/https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

#编辑yaml配置文件
vim recommended.yaml
#修改如下内容:
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort # 新增
ports:
- port: 443
targetPort: 8443
nodePort: 30009 # 新增
selector:
k8s-app: kubernetes-dashboard


#部署
kubectl create -f recommended.yaml
#查看Pod和服务信息
kubectl get pod,svc -n kubernetes-dashboard


#浏览器访问:https://192.168.60.101:30009
#访问dashboard时需要token令牌才能使用,故需要回到Master节点执行如下命令创建账户token令牌:
#创建账户
kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard
#授权账户
kubectl create clusterrolebinding dashboard-admin-rb --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin
#获取账户秘钥
#kubectl get secrets -n kubernetes-dashboard | grep dashboard-admin
#根据账户秘钥获取token令牌
#kubectl describe secrets <账户秘钥> -n kubernetes-dashboard
#根据账户秘钥获取token令牌
kubectl describe secrets $(kubectl get secrets -n kubernetes-dashboard | grep dashboard-admin | awk '{print $1}') -n kubernetes-dashboard

默认 Chrome 等浏览器由于 SSL 证书不受信任的原因无法正常访问 Dashboard,需要如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#生成自签证书
openssl genrsa -out dashboard.key 2048
openssl req -new -out dashboard.csr -key dashboard.key -subj '/CN=10.0.0.10'
openssl x509 -req -days 3650 -in dashboard.csr -signkey dashboard.key -out dashboard.crt

#删除原有证书
kubectl get secret kubernetes-dashboard-certs -n kubernetes-dashboard
kubectl delete secret kubernetes-dashboard-certs -n kubernetes-dashboard

#通过新生成的证书创建secret
kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kubernetes-dashboard

#查看dashboard的pod
kubectl get pod -n kubernetes-dashboard | grep kubernetes-dashboard
#删除原有pod即可(会自动创建新的pod)
kubectl delete pod $(kubectl get pod -n kubernetes-dashboard | grep kubernetes-dashboard | awk '{print $1}') -n kubernetes-dashboard

#再次查看,等待重建的pod创建完成
kubectl get pod -n kubernetes-dashboard | grep kubernetes-dashboard

以上操作完成就可以使用 Chrome 访问 Dashboard 了。

提示:火狐浏览器不需要如上操作也能默认可以访问

参考:https://blog.csdn.net/qq_35078688/article/details/130662916

效果如下:

image-20231106151426283

image-20231106151548589

拓展知识

重置节点

如果集群部署出问题了,需要重新部署,可以先重置所有节点然后再重新部署,其中重置节点操作如下:

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
#重置节点(Master或Node节点通用)
kubeadm reset

#关闭kubelet和docker服务
systemctl stop kubelet
systemctl stop docker

#清除遗留文件
rm -rf /root/.kube
rm -rf /etc/kubernetes
rm -rf /var/lib/kubelet/*
rm -rf /var/lib/etcd
rm -rf /etc/cni/
rm -rf /var/lib/cni/

#清理ipvsadm
ipvsadm -C

#重置防火墙
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

#重置相关网卡配置
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig docker0 down
ip link delete cni0
ip link delete flannel.1

#重启kubelet和docker服务
systemctl start kubelet
systemctl start docker
1
2
3
4
5
#如果仅重置Node节点,需要在Master节点中执行如下命令从集群中删除相关节点
#将节点设置为不可调度状态,以防止新的 Pod 被调度到该节点上
kubectl cordon <node-name>
#从集群中删除该节点
kubectl delete node <node-name>

卸载 k8s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#停止并删除 Kubernetes 服务
systemctl stop kubelet
systemctl disable kubelet
kubeadm reset

#删除 Kubernetes 软件包
yum remove -y kubelet kubeadm kubectl

#删除相关的 Docker 容器和镜像
docker rm -f $(sudo docker ps -aq)
docker rmi -f $(sudo docker images -q)

#删除 Kubernetes 相关的配置文件和目录
rm -rf ~/.kube /etc/kubernetes

在任意节点使用 kubectl

1
2
3
4
5
6
# 1. 将 master 节点中 /etc/kubernetes/admin.conf 拷贝到需要运行的服务器的 /etc/kubernetes 目录中
scp /etc/kubernetes/admin.conf root@k8s-node1:/etc/kubernetes

# 2. 在对应的服务器上配置环境变量
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile

三、参考



----------- 本文结束 -----------




如果你觉得我的文章对你有帮助,你可以打赏我哦~
0%