k8s架构以及核心组件介绍:
Master
- API Server (接口中心) j接口服务,基于rest风格开放的k8s接口服务
- kube Controller Manager:管理各个类型的控制器,针对k8s中的各种资源进行管理
- node controller节点控制器:负责在节点出现故障时进行通知和响应
- job controller 任务控制器:监测代表一次性任务的job对象,然后创建pods来运行这些任务直至完成
- EndpointSlice Controller 端点分片控制器:填充端点分片对象(以提供service 和pod之间的连接)
- ServiceAccount Controller 服务账号控制器:为新的命名空间创建默认的服务账号
- cloud Controller Mannager :云控制器管理器,第三方云平台提供的控制器api对接管理功能
- kube Scheduler 调度器 负责将pod基于一定算法将其调用到更合适的节点node上
- ETCD:kv分布式数据库,提供了基于raft算法实现自主的集群高可用
Node:
- Kubelet:负责pod的生命周期、存储、网络
- Kube-Proxy:网络代理 负责service的服务发现以及负载均衡(基于iptables实现)
- Container Runtime:基于docker|continerd|CRI-O的容器运行时环境。(以docker为例,每个节点需要安装docker)
附加组件:
kube-dns:负责为整个集群提供DNS服务 (服务名:ip)
igress controller:为服务提供外网接口
Prometheus:监控
Dashboard UI:图形界面操作
核心概念:
POD:
无状态服务:(如 nginx,不会存储数据到磁盘)
- ReplicationController(RC 新版本废弃):针对某一单一的pod动态更新pod副本数,扩容缩容
- ReplicaSet(RS):动态更新pod副本数,扩容缩容,可以通过selector来选择对哪些label的pod生效,可以指定单个或者一组pod,比RC更加灵活
- Deployment :针对RS的更高层次的封装,提供了更丰富的部署相关功能(自动创建RS/pod,滚动升级/回滚,平滑扩容和缩容,暂停与恢复deployment)
有状态服务:(如 mysql redis 会存储数据到磁盘)
- StatefulSet:稳定持久化存储,稳定的网络标志,有序部署,有序扩展,有序收缩,有序删除(例如,主从顺序)
守护进程:
- DeamonSet:保证在每个node上面都运行一个容器副本,常用来,日志收集logstash,系统监控:Prometheus,系统程序:proxy,dns等
任务/定时任务
- Job
- CronJob
service : pod与pod之间暴露端口的网络通讯
ingress :将k8s内部服务暴露给外网访问的服务
volume:数据卷,共享pod中容器使用的数据,用来持久化数据,比如数据库数据
CSI:容器标准化接口,暴露容器内存储的接口标准,volume 插件实现这套接口
configmap:暴露容器内配置,外部修改,自动更新部署
downwardapi:共享pod信息给里面的容器访问
k8s调用流程:
1.用户通过 kubectl(命令行工具)/Dashboard(可视化界面) 来与Master(api server)通讯进行操作,例如部署新应用
2.Master(api server) 接收到请求,并将其存储到Etcd
3.Master(Watcher和controllers)通过检测到etcd资源变化,进行操作
4.Master(ReplicaSet watcher/controller)检测到新的app,创建新的pod达到期望的实例个数
5.Master(Scheduler)将新的pod分配到Node(Kubelet)
6.Node(Kubelet)检测到pods,通过容器运行时部署它们,回传信息给Master(api server)
7.Node(Kubeproxy) 管理pod网络,服务发现 负载均衡
k8s部署(kubeadmin):
(操作系统centos7,docker 20+,k8s 1.23.6)
1.初始操作(所有节点):三台机器为例 192.168.0.(111 - 113)
- 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
- 关闭selinux
sed -i 's/enforcing/disabled/' '/etc/selinux/config'
setenforce 0
- 关闭swap
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
- 设置主机名
hostnamectl set-hostname k8s-master|k8s-node1|k8s-node2
- 添加host给每台机器
/etc/hosts
192.168.0.111 k8s-master
192.168.0.112 k8s-node1
192.168.0.113 k8s-node2
- 时间同步
yum install ntpdate -y
ntpdate time.windows.com
2.安装基础软件(所有节点):
- 安装docker
添加源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 添加阿里云源
cat <<EOF > kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enable=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
mv kubernetes.repo /etc/yum.repos.d/
- 安装kubeadmin kubelet kubectl
yum install -y kubelet-1.23.6 kubeadmin-1.23.6 kubectl-1.23.6 docker-ce-20.10.0 docker-ce-cli-20.10.0
systemctl enable kubelet
systemctl enable docker
systemctl start kubelet
systemctl start docker
- 修改docker配置 使用systemd作为cgroupdriver
cat <<EOF > daemon.json
{
"exec-opts":["native.cgroupdriver=systemd"],
"registry-mirrors":["https://ud6340vz.mirror.aliyuncs.com"]
}
EOF
mv daemon.json /etc/docker/
systemctl daemon-reload
systemctl restart docker
注:初始化时可能需要tc
yum install -y tc即可
3.初始化master节点(master上执行):
kubeadmin init --image-repository=registry.aliyuncs.com/google_containers
注:初始化完成后会有一个加入命令,可以保存起来。kubeadmin token create --print-join-command
初始化完成后执行下面三个命令:
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
为让其他节点也能使用kubectl工具:
scp /etc/kubernetes/admin.conf root@node1|node2:/etc/kubernetes/admin.conf
然后分别在node1 node2 上也执行下面三个命令
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
4.加入node1 node2 到集群
kubeadmin join master:6443 --token xxx --discovery-token-ca-cert-hasg xxx
5.安装网络插件(部署好kubectl 都可以执行):
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yaml
kubectl get nodes
注:
flannel是coreos开源的针对k8s的网络服务,其目的是解决k8s集群中各主机pod之间的通信问题,借助etcd维护网络ip地址分配,并为每个node节点分配一个不同的ip地址段
在每个节点创建文件/run/flannel/subnet.env写入以下内容,等一会儿即可
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
以上部署完成。
k8s命令
参考官方文档:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands
POD:
资源清单 - 部分
apiVersion: v1
kind:Pod
metadata:#pod相关元数据,描述pod数据
name: nginx-demo
labels:# 标签
type: app
version: 1.0.0
namespace: 'default'
spec:#期望pod按照这里面的描述进行创建
terminationGracePeriodSeconds:30
containers: 对于pod中容器描述
- name: nginx
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
command:
- nginx
- -g
- 'daemon off;'
args:
workingDir: /usr/share/nginx/html
ports:
- name: http
containerPort: 80
protocol: TCP
env:
- name: JVM_OPTS
value: '-Xm sdsa'
resources:
requests: 最少需要多少资源
cpu:100m
memory:128m
limits:最多需要多少资源
cpu: 200m
memory:128m
restartPolicy:Onfailure
lifecycle:# 生命周期配置
postStart:#生命周期启动阶段做的事情
exec:
command:
- sh
- -c
preStop:
exec:
command:
starupProde:#启动探针,启动后执行下列两个探针任务
livebusnessProde:#存活探针,某一条件判定不存活按照一定规则重启
readinessProde:#就绪探针,某一条件判断成功就绪 做一些事情
- kubectl create -f xxx.yaml
- kubectl delete po xxx
- kubectl describe po nginx
Deployment
适用无状态应用部署
创建:
- kubctl create deploy nginx-deploy --image=nginx:1.7.9
- kubctl get deloyments
- kubctl get replicaset
- kubctl get deploy nginx-deploy -o yaml
apiVersion: apps/v1
kind:Deployment
metadata:
labels:
app:nginx-deploy
name:nginx-deploy
namespace:default
spec:
replicas: 1
revisionHistoryLimit:10
selector:
matchLabels:
app:nginx-deploy
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type:RollingUpdate
template:
metadata:
labels:
app:nginx-deploy
spec:
containers:
- image:nginx:1.7.9
imagePullPolicy:IfNotPresent
name:nginx
rstartPolicy:Always
terminationGracePeriodSeconds: 30
滚动更新:
只有修改了deployment配置文件中的template中的属性后,才会触发更新操作
- kubectl edit deploy nginx-deploy
- kubectl set image deployment/nginx-deploy nginx=nginx:1.7.9
回滚:
- kubectl rollout history deployment/nginx-deploy
- kubectl rollout history deployment/nginx-deploy --revision=2
- kebectl rollout undo deployment/nginx-deploy --to-revision=2
如果spec.revisionHistoryLimit设置为0 则不允许deploy回退了
扩容缩容:
- kubectl edit deploy nginx-deploy
- kubectl scale --replicas 3 deploy nginx-deploy
暂停恢复:
由于每次对template信息发生修改后,都会出发更新,实际上只需要执行最后一次修改即可,这种情况可以使用暂停
- kubectl rollout pause deployment nginx-deploy
- kubectl rollout resume deploy nginx-deploy
删除:
- kubectl delete deploy nginx-deploy
StatefulSet
适用有状态服务部署
创建:
web.yaml
---
apiVersion: v1
kind: Service
metadata:
name:nginx
labels:
app:nginx
spec:
ports:
- port:80
name: web
clusterIP:None
selector:
app:nginx
---
apiVersion:apps/v1
kind:StatefulSet
metadata:
name:web
spec:
serviceName:"nginx"
replicas:2
selector:
matchLabels:
app:nginx
template:
metadata:
labels:
app:nginx
spec:
containers:
- name: nginx
image:nginx:1.7.9
ports:# 容器内部要暴露的端口
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath:/usr/share/nginx/html
updateStrategy:
rollingUpdate:
partition:0# 假设有5个pod,那么此时更新只会更新那些索引id >= 3的pod,实现灰度发布 逐步更新
type:RollingUpdate
volumeClaimTemplates:
- metadata:
name:www
annotations:
volume.alpha.kubernetes.io/storage-class: anything
spec:
accessModes:["ReadWriteOnce"]
resources:
requests:
storage:1Gi# 需要1个G的存储资源
-kubectl create -f web.yaml
-kubectl get sts(statefulset 缩写)
-kubectl get svc(service 缩写)
-kubectl get pvc
-kubectl replace sts web -f web.yaml
-kubectl run -it --image busybox dns-test --restart=Never --rm /bin/sh
ping web-0.nginx
扩容缩容:
有序操作,保证顺序扩容缩容
-kubectl scale statefulset web --replicas=5
-kubectl patch statefulset web -p '{"spec":{"replicas":3}}'
滚动更新:
statefulset 也可以采用滚动更新策略,同时修改pod template属性后触发,但是由于statefulset下的pod是有序的,更新时会按照顺序滚动更新
灰度发布:(金丝雀发布,目标:将项目上线后产生的影响降到最低,只更新一小部分,逐步放开更新全部,利用template中updateStrategy的partition控制)
OnDelete:修改template中updateStrategy的type为OnDelete 即使修改了模板也不会更新了,只有delete pod web-x 删除时才会更新
删除:
- kubectl delete statefulset web
- kubectl delete statefulset web --cascade=false
DaemonSet
为每一个匹配的node部署一个守护进程(监控,数据清理,日志收集等等服务,只要打了匹配标签的机器,会自动部署上去)匹配方式如下:
nodeSelector:只调度到匹配指定label的node上
fluentd.yaml:
apiVersion:apps/v1
kind:DaemonSet
metadata:
name:fluentd
spec:
selector:
matchLabels:
app:logging
template:
metadata:
labels:
app:logging
id:fluentd
name:fluentd
spec:
nodeSelector:# 节点选择器
type:microservices
containers:
- name:fluentd-es
image:agilestacks/fluentd-elasticsearch:v1.3.0
env:
- name:FLUENTD_ARGS
value: -qq
volumeMounts:
- name: containers
mountPath: /var/lib/docker/containers
- name: varlog
mountPath:/var/log
volumes:# 定义数据卷类型
- hostPath:
path:/var/lib/docker/containers
name: containers
- hostPath:
path:/var/log
name: varlog
- kubectl label node k8s-node1 type=microservices
- kubectl create -f fluentd.yaml
- kubectl get daemonset(ds)
nodeAffinity:功能更丰富的node选择器,比如支持集合操作
podAffinity:调度到满足条件的pod所在的node上
HPA:(Horizontal Pod Autoscaler)
Pod 自动扩容,根据cpu使用率或者自定义指标(metrics)自动对pod进行扩容缩容
- 控制器管理每隔30s(可以通过-horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况
- 支持三种metrics类型
预定义metrics (pod cpu利用率方式计算)
自定义,以原始值(raw value)方式计算
自定义object metrics
- 支持两种metrics查询方式:Heapster 和自定义rest api
- 支持多metrics
cpu 内存指标监控:
前提必须配置resources.requests.cpu|memory才可以
新增配置:
resources: # 资源配置
requests: 最少需要多少资源
cpu:100m
memory:128m
limits:最多需要多少资源
cpu: 200m
memory:128m
- kubectl replace -f nginx-deploy.yaml #替换yaml
- kubectl autoscale deploy nginx-deploy --cpu-percent=20 --min=2 --max=5#创建hpa
- kubectl get hpa # 查看信息
服务发现(Service)内部
nginx-svc.yaml
apiVersion:v1
kind: Service
metadata:
name:nginx-svc
labels:
app:nginx
spec:
selector:
app:nginx-deploy
ports:# 端口映射
- port:80
targetPort: 80
nodePort: 32000
name:web
type:NodePort
- kubectl create -f nginx-svc.yaml
- kubectl get svc
- kubectl exec -it dns-test --sh curl http://nginx-svc
代理k8s外部服务:
编写service文件时,不指定selector,自己创建endpoint:
nginx-svc-ext.yaml
apiVersion:v1
kind: Service
metadata:
name:nginx-svc-ext
labels:
app:nginx
spec:
ports:# 端口映射
- port:80
targetPort: 80
name:web
type:ClusterIP
nginx-ep-ext.yaml
apiVersion:v1
kind: EndPoints
metadata:
labels:
app:nginx-svc
name: nginx-svc-ext
namespace:default
subsets:
- address:
- ip: <任一网站ip地址>
ports:
- name:web
port: 80
protocol:TCP
- kubectl create -f nginx-svc-ext.yaml
- kubectl create -f nginx-ep-ext.yaml
curl http://nginx-svc-ext
流程 k8s内部访问service 然后到endpoint 再到目标网站或者接口
反向代理外部域名服务:
apiVersion:v1
kind:Service
metadata:
labels:
app:xxxx.com-domain
name:xxxx.com-domain
spec:
type:ExternalName
externalName:xxxx.cn
curl http://xxxx.com-domain
服务发现(ingress)外部
用户访问ingress -> service -> pod
安装ingress-nginx
- 安装helm包管理器(具体操作查看官网)
下载解压设置环境变量
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
- helm pull ingress-nginx
- 修改values.yaml
仓库国内仓库:registry.cn-hangzhou.aliyuncs.com
image:google_containers/nginx-ingress-controller
webhook镜像 image:google_containers/kube-webhook-certgen
kind:DaemonSet nodeSelector 新增
ingress:"true"
dnsPolicy:ClusterFirstWithHostNet
hostNetWork:"true"
type:ClusterIP
- kubectl create namespace ingress-nginx
- kubectl label node k8s-master ingress=true
- helm install ingress-nginx -n ingress-nginx .
ingress.yaml
apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
name: ingress-test
annotations:
kubernetes.io/ingress.class:"nginx"
spec:
rules:
- host: xxxxx.com
http:
path:
- pathType:Prefix
backend:
service:
name:nginx-svc
port:
number:80
path:/api
配置管理
ConfigMap:
kubectl create configmap -h
kubectl create cm test-config --from-file=./test/
加密数据配置Secret:加密配置
kubectl create secret test-config --from-file=./test/
SubPath:避免覆盖
配置热更新:edit | replace
kubectl edit cm test-config
kubectl create cm test-config --from-file=./test/ --dry-on -o yaml | kubectl replace -f
不可变的Secret和configmap
增加配置 immutable:true禁止修改
持久化存储
volumes:
- HostPath: 将节点上的摁键或目录挂载到pod上,此时目录变成持久化存储目录,即使pod删除重启,也可以重新加载到目录。该目录下的文件不会丢失
apiVersion: v1
kind:Pod
metadata:
name:test-volume
spec:
containers:
image:nginx
name:nginx-volume
volumeMounts:
mountPath:/test-pd
name:/test-volume
volumes:# 定义数据卷
name:test-volume
hostPath:
path:/data
type:Directory# 空字符串:默认类型,不做任何检查;DirectoryOrCreate:如果给定的path不存在创建一个755的空目录;Directory:这个目录必须存在;FileOrCreate:给定文件不存创建一个655文件;File:文件必须存在;Socket:UNXI套接字,必须存在;CharDevice:字符设备,必须存在;BlockDevice:块设备,必须存在
- EmptyDir:一个pod中不同的container共享数据使用的,因为在pod使用,因此与其他volume区别,当pod被删除,这个emptyDir也会被删除
NFS挂载:nfs能将nfs(网络文件系统)挂载到你的pod中。不想emptydir那样会在删除pod同时删除,nfs内容会在删除pod时保存,卷也只是被卸载,意味着nfs可以预先填充数据,可以在pod之间共享.
apiVersion:v1
kind:Pod
metadata:
name:nfs-test-pd1
spec:
containers:
- image:nginx
name:test-container
volumeMounts:
- mountPath:/user/share/nginx/html
name:test-volume
volumes:
- name: test-volume
nfs:
server:xxx.xxx.xxx.xxx
path:/home/nfs/rw/www
readOnly:false
PV&PVC:
pv:统一存储规范,至于存到什么设备自己设定,pvc:持节卷申领,替pod向pv申领资源。
pv.yaml
apiVersion:v1
kind:PersistentVolume
metadata:
name:pv0001
spec:
capacity:
storage:5Gi
volumeMode:Filesystem
accessModes:# 访问模式 ReadWriteOnce ReadWriteMany ReadOnlyMany ReadOnlyOnce
- ReadWriteOnce
persistentVolumeReclaimpolicy: Retain
storageClassName:slow
mountOptions:
- hard
- nfsvers=4.1
nfs:#连接到nfs
path:/data/nfs/rw/test-pv
server:xxx.xxx.xxx.xxx
pvc.yaml
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:nfs-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode:Filesystem
resources:
requests:
storage:5Gi
storageClassName:slow
selector:
pod.yaml
...
spec:
containers:
...
volumeMounts:
- mountPath:/test-pd
name:test-volume
volumes:
- name:test-volume
PersistentVolumeClaim:
claimName:nfs-pvc
StorageClass:
每个sc都又一个制备器provisioner,用来决定使用哪个卷插件制备pv,自动创建pv
nfs-storage-class.yaml
apiVersion:storage.k8s.io/v1
kind:StorageClass
metadata:
name:managed-nfs-storage
provisioner:fuseim.pri/ifs
parameters:
archiveOnDelete:"false"
reclaimPolicy: Retain
volumeBindingMode:Immediate
---
kind:Service
嵌套service配置
---
kind:statefulset
...
spec:
template:
...
spec:
containers:
- image: nginx
volumeMounts:
- mountPath:/usr/share/nginx/html
name:nginx-sc-test-pvc
VolumeClaimTemplates:
- metadata:
name:nginx-sc-test-pvc
spec:
storageClassName:managed-nfs-storage
accessNodes:
- ReadWriteMany
rouserces:
requests:
storage: 1Gi
高级调度
CronJob 计划任务:
与linux crontab相同,注意:cronjob执行时间时controller manager的时间
apiVersion:batch/v1
kind:CronJob
metadata:
name:hello
spec:
concurrencyPolicy:Allow
failedJobsHistoryLimit:1
successfulJobsHistoryLimit:3
suspend: false
startingDeadlineSeconds:30
schedule:"* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name:hello
image:busybox:1.28
imagePullPolicy:IfNotPresent
command:
- /bin/sh
- -c
- date;echo hello from the k8s clusterIP
restartPolicy:OnFailure
Init Container:
相对于生命周期钩子函数postStart,在真正启动容器前,先启动init c,在初始化容器中完成真实容器初始化操作,完成后启动真实的容器
在pod创建的模板template中配置initContainers参数:
spec:
initContainers:
- image: nginx
imagePullPolicy:IfNotPresent
commond: ["sh", "-c", "echo 'inited' >> /.init"]
name:init-test
污点和容忍:配置污点的node不会生成pod,配置了容忍的pod会部署上去。
NoSchedule:如果不能容忍,那么pod无法调度这个节点上
NoExecute:不能执行,已经执行的会删除
亲和力(Affinity):
依据条件筛选更有条件匹配的pod node 调度。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏