K8S快速入门(二)
控制器
控制器是什么?
控制器是k8s内置的管理工具。可以帮助用户实现Pod的自动部署、自维护、扩容、翻滚更新等功能的自动化程序
为什么要使用控制器?
有大量的Pod需要维护管理
需要维护Pod的健康状态
控制器可以像机器人一样可以替用户完成维护管理的工作
Deployment控制器
最常用的无状态服务控制器,由Deployment、ReplicaSet、Pod组成、支持集群扩容缩容、滚动、更新、自动维护Pod可用性及副本数量等功能
ReplicaSet和Pod由Deployment自动管理,用户无需干预
Deployment
功能
需要service资源对象来对其资源进行访问
当集群中有Pod被删除,Deploy会自动创建新的Pod来维护集群的完整性
当Pod标签去掉时,会被踢出集群(谁有标签谁才可以在集群中)
集群扩缩容
滚动更新策略
历史版本及回滚
在这里面,需要新了解的配置项就是spec下面几个选项:
replicas:指定副本数量,其实就是当前rs创建出来的pod的数量,默认为1
selector:选择器,它的作用是建立pod控制器和pod之间的关联关系,采用的Label Selector机制,在pod模板上定义label,在控制器上定义选择器,就可以表明当前控制器能管理哪些pod了
template:模板,就是当前控制器创建pod所使用的模板板
imagePullPolicy: 是确保容器总是使用最新版本的镜像
IfNotPresent: 仅当镜像在本地不存在时,才被拉取
Never:: 设镜像已经存在于本地,不会尝试拉取镜像
always: 确保每次容器启动时都会拉取最新的镜像
[root@master ~]# vim mydeploy.yaml
---
kind: Deployment # 资源对象类型
apiVersion: apps/v1 # 版本
metadata: # 元数据
name: myweb # 名称
spec: # 详细定义
replicas: 2 # 副本数量
strategy: # 策略
type: RollingUpdate # 滚动更新策略
rollingUpdate: # 滚动更新
maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
maxUnavailable: 30% # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
selector: # 定义标签选择器
matchLabels: # 支持 matchExpressions 表达式语法
app: httpd # 通过标签来确定那个 Pod 由它来管理
template: # 定义用来创建 Pod 的模板,以下为 Pod 定义
metadata: # Pod元数据
labels: # 名称由控制器生成
app: httpd # 这里只能定义标签
spec: # Pod的详细定义
restartPolicy: Always # 重启策略
containers: # 容器定义
- name: webserver # 容器名称
image: myos:httpd # 创建容器使用的容器
imagePullPolicy: Always # 镜像下载策略
扩缩容
[root@master ~]# kubectl scale deployment myweb(Deployment名字) --replicas=3(指定Pod数量)
# 1、创建deployment
[root@master ~]# kubectl create -f nginx-deployment.yaml --record=true
deployment.apps/nginx-deployment created
# 2、查看deployment
# UP-TO-DATE 最新版本的pod的数量
# AVAILABLE 当前可用的pod的数量
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl get deploy myweb -n your_spacename
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 15s
[root@master ~]# kubectl get pods -n your_namespace
NAME READY STATUS RESTARTS AGE
nginx-deployment-6696798b78-d2c8n 1/1 Running 0 4m19s
nginx-deployment-6696798b78-jxmdq 1/1 Running 0 94s
nginx-deployment-6696798b78-mktqv 1/1 Running 0 93s
镜像更新
deployment支持两种更新策略:重建更新和滚动更新,可以通过strategy指定策略类型,支持两个属性:
strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
type:指定策略类型,支持两种策略
Recreate:在创建出新的Pod之前会先杀掉所有已存在的Pod
RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
rollingUpdate:当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%。
maxSurge: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。
滚动更新策略
deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能,下面具体来看.
kubectl rollout: 版本升级相关功能,支持下面的选项
status 显示当前升级状态
history 显示 升级历史记录
pause 暂停版本升级过程
resume 继续已经暂停的版本升级过程
restart 重启版本升级过程
undo 回滚到上一级版本(可以使用–to-revision回滚到指定版本)
[root@master ~]# kubectl get deployments.apps myweb -o yaml
......
spec:
revisionHistoryLimit: 10 # 保留10个历史版本
strategy: # 更新策略
rollingUpdate: # 滚动更新策略
maxSurge: 25% # 允许最大副本25%超量
maxUnavailable: 25% # 允许最小副本25%不足
type: RollingUpdate # 更新方式[Recreate,RollingUpdate]
template:
spec:
containers:
- name: webserver
image: myos:httpd
imagePullPolicy: Always # 镜像下载策略[Always,Never,ifNotPresent]
......
# 修改镜像,滚动更新集群
[root@master ~]# kubectl set image deployment myweb webserver=myos:nginx
deployment.apps/myweb image updated
# 给新版本添加注释信息
[root@master ~]# kubectl annotate deployments myweb kubernetes.io/change-
cause="nginx.v1"
deployment.apps/myweb annotated
# 查看历史版本信息
[root@master ~]# kubectl rollout history deployment myweb
deployment.apps/myweb
REVISION CHANGE-CAUSE
1 httpd:v1
2 nginx.v1
# 访问验证服务
[root@master ~]# curl -m 3 http://10.245.1.80
Nginx is running !
版本回滚
# 历史版本与回滚
[root@master ~]# kubectl rollout undo deployment myweb --to-revision 1
deployment.apps/myweb rolled back
[root@master ~]# curl -m 3 http://10.245.1.80
Welcome to The Apache.
[root@master ~]# kubectl rollout history deployment myweb
deployment.apps/myweb
REVISION CHANGE-CAUSE
2 nginx.v1
3 httpd:v1
金丝雀发布
Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作。
比如有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布。
# 1、更新deployment的版本,并配置暂停deployment
[root@master ~]# kubectl set image deploy your_deploy_name nginx=nginx:1.17.4 -n your_namespace && kubectl rollout pause deployment your_deploy_name -n your_namespace
deployment.apps/nginx-deployment image updated
deployment.apps/nginx-deployment paused
# 2、观察更新状态
# - your_deploy_name 你的deploy名称
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl rollout status deploy your_deploy_name -n your_namespace
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 4 new replicas have been updated...
# 3、监控更新的过程,可以看到已经新增了一个资源,但是并未按照预期的状态去删除一个旧的资源,就是因为使用了pause暂停命令
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl get rs -n your_namespace -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES
nginx-deployment-5d89bdfbf9 3 3 3 19m nginx nginx:1.17.1
nginx-deployment-675d469f8b 0 0 0 14m nginx nginx:1.17.2
nginx-deployment-6c9f56fcfb 2 2 2 3m16s nginx nginx:1.17.4
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl get pods -n your_namespace
NAME READY STATUS RESTARTS AGE
nginx-deployment-5d89bdfbf9-rj8sq 1/1 Running 0 7m33s
nginx-deployment-5d89bdfbf9-ttwgg 1/1 Running 0 7m35s
nginx-deployment-5d89bdfbf9-v4wvc 1/1 Running 0 7m34s
nginx-deployment-6c9f56fcfb-996rt 1/1 Running 0 3m31s
nginx-deployment-6c9f56fcfb-j2gtj 1/1 Running 0 3m31s
# 4、确保更新的pod没问题了,继续更新
# - your_deploy_name 你的deploy名称
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl rollout resume deploy your_deploy_name -n your_namespace
deployment.apps/nginx-deployment resumed
# 5、查看最后的更新情况
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl get rs -n your_namespace -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES
nginx-deployment-5d89bdfbf9 0 0 0 21m nginx nginx:1.17.1
nginx-deployment-675d469f8b 0 0 0 16m nginx nginx:1.17.2
nginx-deployment-6c9f56fcfb 4 4 4 5m11s nginx nginx:1.17.4
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl get pods -n your_namespace
NAME READY STATUS RESTARTS AGE
nginx-deployment-6c9f56fcfb-7bfwh 1/1 Running 0 37s
nginx-deployment-6c9f56fcfb-996rt 1/1 Running 0 5m27s
nginx-deployment-6c9f56fcfb-j2gtj 1/1 Running 0 5m27s
nginx-deployment-6c9f56fcfb-rf84v 1/1 Running 0 37s
删除控制器的方法
# 删除控制器方法1
[root@master ~]# kubectl delete deployments myweb
deployment.apps "myweb" deleted
# 删除控制器方法2
[root@master ~]# kubectl delete -f mydeploy.yaml
deployment.apps "myweb" deleted
DaemonSet
> DaemonSet控制器
无法自定义副本数量
所创建的Pod与node节点绑定
每个node上都会允许一个Pod
当有新Node加入集群时,会为他新增Pod副本,当Node从集群移除时,这些Pod也会被回收,
[root@master ~]# vim myds.yaml
---
kind: DaemonSet # 资源对象类型
apiVersion: apps/v1 # 版本
metadata: # 元数据
name: myds # 名称
spec: # 详细定义
selector: # 定义标签选择器
matchLabels: # 支持 matchExpressions 表达式语法
app: httpd # 通过标签来确定那个 Pod 由它来管理
template: # 定义用来创建 Pod 的模板,以下为 Pod 定义
metadata:
labels:
app: httpd
spec:
restartPolicy: Always
containers:
- name: webserver
image: myos:httpd
imagePullPolicy: Always
[root@master ~]# kubectl apply -f myds.yaml
daemonset.apps/myds created
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
NOMINATED NODE READINESS GATES
myds-78b2h 1/1 Running 0 31s 10.244.153.154 node-0005
<none> <none>
myds-78pgb 1/1 Running 0 31s 10.244.243.226 node-0003
<none> <none>
myds-cg2sv 1/1 Running 0 31s 10.244.147.30 node-0002
<none> <none>
myds-pp7s6 1/1 Running 0 31s 10.244.240.162 node-0004
<none> <none>
myds-qrp82 1/1 Running 0 32s 10.244.21.155 node-0001
<none> <none>
DS控制器会受到污点策略的影响
[root@master ~]# kubectl taint node node-0001 k=v:NoSchedule
node/node-0001 tainted
[root@master ~]# kubectl delete -f myds.yaml
daemonset.apps "myds" deleted
[root@master ~]# kubectl apply -f myds.yaml
daemonset.apps/myds created
# 有污点不会部署,特殊需求可以设置容忍策略
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myds-fxlgq 1/1 Running 0 33s
myds-j5779 1/1 Running 0 33s
myds-nb6bv 1/1 Running 0 33s
myds-vkk6x 1/1 Running 0 33s
# 删除污点后会立即部署
[root@master ~]# kubectl taint node node-0001 k=v:NoSchedule-
node/node-0001 untainted
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myds-bq2nv 1/1 Running 0 3s
myds-fxlgq 1/1 Running 0 114s
myds-j5779 1/1 Running 0 114s
myds-nb6bv 1/1 Running 0 114s
myds-vkk6x 1/1 Running 0 114s
# 删除控制器
[root@master ~]# kubectl delete -f myds.yaml
daemonset.apps "myds" deleted
Job/CronJob
Job
单任务控制器,执行一次任务
CronJob是Job的升级版,基于时间管理的Job控制器
restartPOlicy策略会判断exit状态码,状态为0表示正常,其他都是失败
任务执行出错,会重新执行该任务
[root@master ~]# vim myjob.yaml
---
kind: Job
apiVersion: batch/v1
metadata:
name: myjob
spec:
template: # 以下定义 Pod 模板
spec:
restartPolicy: OnFailure
containers:
- name: myjob
image: myos:8.5
command: ["/bin/bash"]
args:
- -c
- |
sleep 3
exit $((RANDOM%2))
[root@master ~]# kubectl apply -f myjob.yaml
job.batch/myjob created
# 失败了会重启
[root@master ~]# kubectl get pods -l job-name=myjob -w
NAME READY STATUS RESTARTS AGE
myjob-plnhc 1/1 Running 0 3s
myjob-plnhc 0/1 Completed 0 4s
myjob-plnhc 0/1 Completed 0 5s
myjob-plnhc 0/1 Completed 0 6s
myjob-plnhc 0/1 Completed 0 6s
[root@master ~]# kubectl get jobs.batch
NAME COMPLETIONS DURATION AGE
myjob 1/1 6s 91s
# 删除Job控制器
[root@master ~]# kubectl delete -f myjob.yaml
job.batch "myjob" deleted
CronJob
时间定义 schedule: 分 时 日 月 周
会按照时间周期运行
只保留执行三次的结果,多余被删除
[root@master ~]# vim mycj.yaml
---
kind: CronJob
apiVersion: batch/v1
metadata:
name: mycj
spec:
schedule: "* * * * 1-5"
jobTemplate: # 以下定义Job模板
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: myjob
image: myos:8.5
command: ["/bin/bash"]
args:
- -c
- |
sleep 3
exit $((RANDOM%2))
[root@master ~]# kubectl apply -f mycj.yaml
cronjob.batch/mycj created
[root@master ~]# kubectl get cronjobs
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
mycj * * * * 1-5 False 0 <none> 14s
# 按照时间周期,每分钟触发一个任务
[root@master ~]# kubectl get jobs -w
NAME COMPLETIONS DURATION AGE
mycj-28263259 1/1 29s 70s
mycj-28263260 1/1 6s 10s
mycj-28263261 0/1 0s
mycj-28263261 0/1 0s 0s
mycj-28263261 0/1 2s 2s
mycj-28263261 0/1 5s 5s
mycj-28263261 0/1 5s 5s
# 保留三次结果,多余的会被删除
[root@master ~]# kubectl get jobs
NAME COMPLETIONS DURATION AGE
mycj-28263261 1/1 24s 2m13s
mycj-28263262 1/1 27s 73s
mycj-28263263 1/1 6s 13s
# 删除CJ控制器
[root@master ~]# kubectl delete -f mycj.yaml
cronjob.batch "mycj" deleted
基础控制器的区别
Deployment 控制器是最常用的 Controller,可以管理 Pod 的多个副本,并确保 Pod 按照期望的状态运行。它支持两种更新策略:滚动更新和重新创建,默认为滚动更新。在 Deployment 中,如果存在容器异常退出,会自动创建新的 Pod 进行替代;同时,异常多出来的容器也会自动回收。当某个 Pod 发生故障需要删除并重新启动时,Pod 的名称会发生变化,同时 StatefulSet 会保证副本按照固定的顺序启动、更新或者删除。
DaemonSet 控制器主要用于在每个节点最多只运行一个 Pod 副本的场景。它的名称暗示了其通常用于运行守护进程(daemon)。当有新的节点加入集群时,DaemonSet 控制器会自动在该节点上创建一个 Pod 副本,当有节点从集群中移除时,DaemonSet 控制器会自动回收该节点上的 Pod 副本。
CronJob/Job主要用于运行结束就删除的应用。它并不适合长期持续运行的任务。相反,它的设计目的是为了处理一些特定的、一次性的任务,例如批处理任务、定时任务等。一旦任务完成,Job 控制器就会自动删除相关的 Pod。
StatefulSet
StatefulSet控制器
StatefulSet旨在与有状态的应用及分布式统一使用,涉及了Headless服务、存储卷、DNS等相关知识,是一个宽泛而复杂的话题
Headless服务
在配置StatefulSets的时候,首先要定义一个Headless的服务
在创建Pod的时候会自动把<Pod名称>注册为域名
headless服务
# 配置 headless 服务
[root@master ~]# vim mysvc2.yaml
---
kind: Service
apiVersion: v1
metadata:
name: mysvc2 # 服务名称
spec:
type: ClusterIP
clusterIP: None # 设置IP为None
selector:
app: httpd
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master ~]# kubectl get service mysvc2
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysvc2 ClusterIP None <none> 80/TCP 17s
StatefulSet资源配置文件
[root@master ~]# vim mysts.yaml
---
kind: StatefulSet # 资源对象类型
apiVersion: apps/v1 # 版本
metadata: # 元数据
name: mysts # 名称
spec: # 详细定义
serviceName: mysvc2 # 控制器名称
replicas: 3 # 副本数量
selector: # 定义标签选择器
matchLabels: # 支持 matchExpressions 表达式语法
app: httpd # 通过标签来确定那个 Pod 由它来管理
template: # 定义用来创建 Pod 的模板,以下为 Pod 定义
metadata:
labels:
app: httpd
spec:
restartPolicy: Always
containers:
- name: webserver
image: myos:httpd
imagePullPolicy: Always
[root@master ~]# kubectl apply -f mysts.yaml
statefulset.apps/mysts created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysts-0 1/1 Running 0 8s
mysts-1 1/1 Running 0 7s
mysts-2 1/1 Running 0 6s
[root@master ~]# host mysts-0.mysvc2.default.svc.cluster.local 10.245.0.10
Using domain server:
Name: 10.245.0.10
Address: 10.245.0.10 #53
Aliases:
mysts-0.mysvc2.default.svc.cluster.local has address 10.244.153.159
[root@master ~]# host mysvc2.default.svc.cluster.local 10.245.0.10
Using domain server:
Name: 10.245.0.10
Address: 10.245.0.10 #53
Aliases:
mysvc2.default.svc.cluster.local has address 10.244.147.37
mysvc2.default.svc.cluster.local has address 10.244.153.159
mysvc2.default.svc.cluster.local has address 10.244.240.164
# 删除sts控制器
[root@master ~]# kubectl delete -f mysts.yaml -f mysvc2.yaml
statefulset.apps "mysts" deleted
service "mysvc2" deleted
Horizontal Pod Autoscaler(HPA)控制器
可在k8s集群中基于CPU利用率或其他应用程序提供的度量指标实现水平自动伸缩的功能,自动缩放POD的数量
要在集群中运行,所以先创建集群
也需要ClusterIP服务
创建被监控的资源对象
# 为 Deploy 模板添加资源配额
[root@master ~]# vim mydeploy.yaml
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: myweb
spec:
replicas: 1 # 修改副本数量
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
restartPolicy: Always
containers:
- name: webserver
image: myos:httpd
imagePullPolicy: Always
resources: # 为该资源设置配额
requests: # HPA控制器会根据配额使用情况伸缩集群
cpu: 200m # CPU配额
创建HPA
[root@master ~]# vim myhpa.yaml
---
kind: HorizontalPodAutoscaler # 资源对象类型
apiVersion: autoscaling/v1 # 版本
metadata: # 元数据
name: myweb # 资源对象名称
spec: # 详细定义
minReplicas: 1 # 最少保留的副本数量
maxReplicas: 5 # 最大创建的副本数量
targetCPUUtilizationPercentage: 50 # 警戒值,以百分比计算
scaleTargetRef: # 监控的资源对象
kind: Deployment # 资源对象类型
apiVersion: apps/v1 # 版本
name: myweb # 资源对象名称
[root@master ~]# kubectl apply -f myhpa.yaml
horizontalpodautoscaler.autoscaling/myweb created
# 刚刚创建 unknown 是正常现象,最多等待 60s 就可以正常获取数据
[root@master ~]# kubectl get horizontalpodautoscalers.autoscaling
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
myweb Deployment/myweb <unknown>/50% 1 5 0
[root@master ~]# kubectl get horizontalpodautoscalers.autoscaling
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myweb Deployment/myweb 0%/50% 1 5 1 59s
service
容器带来的问题
自动调度: 在Pod创建之前,用户无法预知Pod所在节点以及Pod的IP地址
一个已经存在的Pod在运行过程中,出现故障,Pod也会在新的节点使用新的IP进行部署
应用程序访问服务时,地址是不能经常转变的
多个相同的Pod如何访问他们上面的服务
service服务原理:
自动感知: 服务会创建一个clusterIP,对应资源地址,不管Pod如何变化,服务总能找到对应的Pod,且clusterIP保持不变
负载均衡: 若服务器后端对应多个Pod,则会通过IPTables/LVS规则 访问请求最终映射到Pod容器内部,自动实现多个容器的负载均衡
自动发现: 服务创建时会自动在内部dns上注册域名
域名: <服务名称>.<名称空间>.svc.cluster.local
Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
Service有4种类型:
ClusterIP:默认值,它是Kubernetes系统自动分配的虚拟IP,只能在集群内部访问
NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务
LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境支持
ExternalName: 把集群外部的服务引入集群内部,直接使用
ClusterIP
默认的ServiceType,通过集群的内部IP暴露服务,选择该值时服务只能够在集群内部访问
默认类型: 实现Pod的自动感知与负载均衡,是最核心的服务类型,但ClusterIP不能对外发布服务,相对外发布服务只能使用NodePort或lngress
工作原理: kube-proxy 是在所有节点上运行的代理,可以实现简单的数据转发,设置更新IPTables/LVS规则,服务创建时,还提供服务地址DNS自动注册与服务发现功能
查看DNS IP: kubectl -n kube-system get service kube-dns
解析域名的软件包: bind-utils
创建service资源文件模板: kubectl create service clusterip mysvc --tcp=80:80 --dry-run=client -o yaml
[root@master ~]# vim mysvc.yaml
---
kind: Service # 资源对象类型
apiVersion: v1 # 版本
metadata: # 元数据
name: mysvc # 资源对象名称
spec: # 详细信息
type: ClusterIP # 服务类型
clusterIP: 10.245.1.80 # 可以设置ClusterIP
selector: # 选择算符
app: web # Pod标签
ports: # 端口
- protocol: TCP # 协议
port: 80 # 监听的端口,service端口
targetPort: 80 # 后端服务器端口,pod端口
nodePort: 31122 # 主机端口
NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务
在 /root/init/init.yaml 查看固定IP的范围及Pod IP的范围
CluseterIP是随机分配的,可以自定义但必须满足CIDR
创建service
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc created
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 9d
mysvc ClusterIP 10.245.186.38 <none> 80/TCP 8s
域名解析
# 安装工具软件包
[root@master ~]# dnf -y install bind-utils
# 查看 DNS 服务地址
[root@master ~]# kubectl -n kube-system get service kube-dns
NAME TYPE LUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.245.0.10 <none> 53/UDP,53/TCP,9153/TCP 9d
# 域名解析测试
[root@master ~]# host mysvc.default.svc.cluster.local 10.245.0.10
Using domain server:
Name: 10.245.0.10
Address: 10.245.0.10#53
Aliases:
mysvc.default.svc.cluster.local has address 10.245.186.38
nodePort
对外发布应用
ClusterIP服务可以解决集群内应用互访的问题,但外部的应用无法访问集群内的资源,某些应
用需要访问集群内的资源,我们就需要对外发布服务。
ClusterIP:默认类型,可以实现Pod的自动感知与负载均衡,是最核心的服务类型,但
ClusterIP不能对外发布服务,如果想对外发布服务可以使用NodePort 或Ingress
NodePort与Ingress:
NodePort: 使用基于端口映射(默认值: 30000-32767)的方式对外发布服务,可以任意发布服务(四层)
Ingress: 使用Ingress控制器(一般由Nginx或HAProxy构成),用来发布http,https服务(七层,只能发布这俩个服务)
7层负载均衡比4层负载均衡更加智能
4层负载均衡比7层负载均衡更加简洁高效
[root@master ~]# vim mysvc1.yaml
---
kind: Service
apiVersion: v1
metadata:
name: mysvc1
spec:
type: NodePort # 服务类型
selector:
app: web
ports:
- protocol: TCP
port: 80
nodePort: 30080 # 映射端口号
targetPort: myhttp
发布服务
[root@master ~]# kubectl apply -f mysvc1.yaml
service/mysvc1 created
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 3h53m
mysvc ClusterIP 10.245.1.80 <none> 80/TCP 3h35m
mysvc1 NodePort 10.245.235.255 <none> 80:30080/TCP 15s
Ingress
Ingress服务由(规则 + 控制器)组成
使用Ingress控制器(一般由Nginx或HAProxy构成),用来发布http,https服务(七层,只能发布这俩个服务)
获取ingress
# 创建文件夹
[root@master ~]# mkdir ingress-controller
[root@master ~]# cd ingress-controller/
# 获取ingress-nginx,本次案例使用的是0.30版本
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
# 修改mandatory.yaml文件中的仓库
# 修改quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
# 为registry.aliyuncs.com/google_containers/nginx-ingress-controller:0.30.0
# 创建ingress-nginx
[root@master ingress-controller]# kubectl apply -f ./
# 查看ingress-nginx
[root@master ingress-controller]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-ingress-controller-fbf967dd5-4qpbp 1/1 Running 0 12h
# 查看service
[root@master ingress-controller]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.98.75.163 <none> 80:32240/TCP,443:31335/TCP 11h
创建ingress
[root@master ingress]# vim mying.yaml
---
kind: Ingress # 资源对象类型
apiVersion: networking.k8s.io/v1 # 资源对象版本
metadata: # 元数据
name: mying # 资源对象名称
spec: # 资源对象定义
ingressClassName: nginx # 使用的类名称
rules: # ingress规则定义
- host: nsd.tedu.cn # 域名定义,没有可以不写
http: # 协议
paths: # 访问的路径定义
- path: / # 访问的url路径
pathType: Prefix # 路径类型:Exact、Prefix
backend: # 后端服务
service: # 服务声明
name: mysvc # 服务名称
port: # 端口号声明
number: 80 # 访问服务的端口号
[root@master ingress]# kubectl apply -f mying.yaml
ingress.networking.k8s.io/mying created
[root@master ingress]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
mying nginx nsd.tedu.cn 192.168.1.51 80 10s
[root@master ingress]# curl -H "Host: nsd.tedu.cn" http://192.168.1.51
Welcome to The Apache.
存储卷管理
容器中的文件在磁盘上是临时存放的,所以:
当容器崩溃或重启,kubelet重启容器后,历史数据会消失
容器被删除,容器内的数据也会消失
多个容器有共享文件或目录的需求
卷概述:
卷是一个抽象化的存储设备
卷可以解决容器崩溃或重启,数据丢失的问题
可以解决容器或Pod被删后数据持久保存的问题
可以解决在多个容器内共享数据的问题
Pod可以同时使用任意数目的卷
持久卷:持久卷是集群中的存储资源,里面的内容不会随着Pod的删除而消失
临时卷:有些应用程序需要额外的存储,但并不关心数据在重启后是否仍可用,卷会遵从Pod的生命周期,与Pod一起创建和删除
使用存储卷:
在Pod.spec下添加volumes字段,配置外部存储卷
在Pod.spec.containers[*]中添加 vloumeMounts字段,声明卷在容器中挂载位置
持久卷
hostPath
本质是使用本地设备,如磁盘,分区,目录等,hostPath的可用性取决于底层节点的可用性,如果节点变的不健康,那hostPath也将不可访问
hostPath卷里面的数据不会随着Pod的结束而消失
[root@master ~]# vim web1.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web1
spec:
volumes: # 卷定义
- name: logdata # 卷名称
hostPath: # 资源类型
path: /var/weblog # 宿主机路径
type: DirectoryOrCreate # 目录不存在就创建
containers:
- name: nginx
image: myos:nginx
volumeMounts: # mount 卷
- name: logdata # 卷名称
mountPath: /usr/local/nginx/logs # 容器内路径
type类型:
DirectoryOrCreate 卷映射对象是一个目录,如果不存在就创建它
Directory 卷映射对象是一个目录,且必须存在
FileOrCreate 卷映射对象是一个文件,如果不存在创建它
File 卷映射对象是一个文件,且必须存在
Socket 卷映射对象是一个Socket套接字,且必须存在
CharDevice 卷映射对象是一个字符设备,且必须存在
BlockDevice 卷映射对象是一个块设备,且必须存在
NFS
NFS 存储
k8s中允许将nfs存储以卷的方式挂载到你的Pod中。在删除Pod时,nfs存储卷会被卸载(umount),而不是被删除。nfs卷可以在不同节点的Pod之间共享数据。
NFS卷的用途
NFS最大的功能就是在不同节点的不同Pod中共享读写数据。本地NSF的客户端可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。
部署
需要一台NFS服务器
在所有节点都需安装NFS(因为Pod是随机调度的,所以为保证NFS存储卷可以正确加载,需在所有node节点上都安装NFS软件工具包)
[root@master ~]# vim nfs.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web1
spec:
volumes: # 卷定义
- name: website # 卷定义
nfs: # NFS 资源类型
server: 192.168.1.10 # NFS 服务器地址
path: /var/webroot # NFS 共享目录
containers:
- name: nginx
image: myos:nginx
volumeMounts: # mount 卷
- name: website # 卷名称
mountPath: /usr/local/nginx/html # 容器内路径
[root@master ~]# kubectl apply -f nfs.yaml
pod/nfs created
PV/PVC
PV: 持久卷,资源提供者,有管理员配置,PV的全称是Persistent Volume,是持久卷
VC: 持久卷声明,资源使用者,根据业务需求来配置,PVC的全称是Persistent VolumeClaim,是持久卷声明
PVC会根据客户的需求,自动找到PV绑定
accessMode:存储卷能提供的访问方式:
ReadWriteOnce: 单节点读写
ReadOnlyMany: 多节点只读
ReadWriteMang: 多节点读写
ReadWriteOnceMangy: 在一个Pod中只读
volumeMode: 提供资源的类型:
Filesystem:文件系统,直接mount就可以使用
Block:块设备,要先格式化在mount
持久卷PV
[root@master ~]# vim pv.yaml
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv-local
spec:
volumeMode: Filesystem # 提供资源的类型[Filesystem,Block]
accessModes: # 存储卷能提供的访问模式
- ReadWriteOnce # 卷支持的模式,支持多种(hostPAth 只支持 RWO)
capacity: # 存储卷能提供的存储空间
storage: 30Gi # 空间大小
persistentVolumeReclaimPolicy: Retain # 数据回收方式(手工回收)
hostPath: # hostPath配置
path: /var/weblog
type: DirectoryOrCreate
---
kind: PersistentVolume
apiVersion: v1
metadate:
name: pv-nfs
spec:
volumeMode: Filesystem # 提供Filesystem访问方式
accessModes: # NFS支持多种访问方式
- ReadWriteOnce # RWO、ROX、RWX
- ReadOnlyMany
- ReadWriteMany
capacity:
storage: 20Gi # 提供的磁盘空间大小
persistentVolumeReclaimPolicy: Retain # 数据手动回收
mountOptions: # mount的参数
- nolock
nfs: # NFS配置
server: 192.168.1.10
path: /var/webroot
[root@master ~]# kubectl apply -f pv.yaml
persistentvolume/pv-local created
persistentvolume/pv-nfs created
[root@master ~]# kubectl get persistentvolume
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-local 30Gi RWO Retain Available 2s
pv-nfs 20Gi RWO,ROX,RWX Retain Available 2s
持久卷声明 PVC
[root@master ~]# vim pvc.yaml
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
spec: # 定义需求
volumeMode: Filesystem # 需要使用Filesystem的存储卷
accessModes:
- ReadWriteOnce # 需要支持RWO的存储卷
resources:
requests:
storage: 25Gi # 最小磁盘空间需求
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc2
spec: # 定义需求
volumeMode: Filesystem # 需要使用Filesystem的存储卷
accessModes:
- ReadWriteMany # 需要支持RWX的存储卷
resources:
requests:
storage: 15Gi # 最小磁盘空间需求
[root@master ~]# kubectl apply -f pvc.yaml
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
[root@master ~]# kubectl get persistentvolumeclaims
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound pv-local 30Gi RWO 17s
pvc2 Bound pv-nfs 20Gi RWO,ROX,RWX 17s
Pod 挂载 PVC
[root@master ~]# vim web1.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web1
spec:
volumes: # 卷定义
- name: logdata # 卷名称
persistentVolumeClaim: # 通过PVC引用存储资源
claimName: pvc1 # PVC名称
- name: website # 卷名称
persistentVolumeClaim: # 通过PVC引用存储资源
claimName: pvc2 # 卷名称
containers:
- name: nginx
image: myos:nginx
volumeMounts: # mount 卷
- name: logdata # 卷名称
mountPath: /usr/local/nginx/logs # 容器内路径
- name: website # 卷名称
mountPath: /usr/local/nginx/html # 容器内路径
临时卷
configMap
提供了向Pod注入配置数据的方法,允许你将配置文件与镜像分离,使容器化的应用具有可移植性
在使用之前就要创建好,不是用来保存数据的,其保存的数据不可超过1MiB
配置环境变量,修改配置文件的参数,数据库地址等
[root@master ~]# vim timezone.yaml
---
kind: ConfigMap
apiVersion: v1
metadata:
name: timezone
data:
TZ: Asia/Shanghai
[root@master ~]# kubectl apply -f timezone.yaml
configmap/timezone created
[root@master ~]# kubectl get configmaps
NAME DATA AGE
kube-root-ca.crt 1 9d
timezone 1 9s
tz 1 3m57s
[root@master ~]# vim web1.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web1
spec:
volumes: # 卷定义
- name: logdata # 卷名称
persistentVolumeClaim: # 通过PVC引用存储资源
claimName: pvc1 # PVC名称
- name: website # 卷名称
persistentVolumeClaim: # 通过PVC引用存储资源
claimName: pvc2 # 卷名称
containers:
- name: nginx
image: myos:nginx
envFrom: # 配置环境变量
- configMapRef: # 调用资源对象
name: timezone # 资源对象名称
volumeMounts: # mount 卷
- name: logdata # 卷名称
mountPath: /usr/local/nginx/logs # 容器内路径
- name: website # 卷名称
mountPath: /usr/local/nginx/html # 容器内路径
[root@master ~]# kubectl delete pods web1
pod "web1" deleted
[root@master ~]# kubectl apply -f web1.yaml
pod/web1 created
[root@master ~]# kubectl exec -it web1 -- date +%T
17:25:37
secret
类似于ConfigMap,专门用于保存机密数据,因为是加密的
一般用于:
配置一些需要加密的环境变量或文件(如 https 证书)
访问需要认证登录的私有镜像仓库(如 harbor 私有仓库)
通用类型
kubectl createsecret generic 名称 [选项/参数]
用于认证登录私有仓库的子类型
kubectl create secret docker-registry 名称 [选项/参数]
用于创建TLS证书的子类型
kubectl create secret tls 名称 [选项/参数]
配置登录密钥
root@master ~]# kubectl create secret docker-registry harbor-auth --docker server=harbor:443 --docker-username="admin" --docker-password="admin123"
secret/harbor-auth created
[root@master ~]# kubectl get secrets harbor-auth -o yaml
apiVersion: v1
data:
.dockerconfigjson:
eyJhdXRocyI6eyJoYXJib3I6NDQzIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6ImFkbWluM
TIzIiwiYXV0aCI6IllXUnRhVzQ2WVdSdGFXNHhNak09In19fQ== # 经过加密的数据
kind: Secret
metadata:
creationTimestamp: "2023-09-22T10:03:02Z"
name: harbor-auth
namespace: default
resourceVersion: "285856"
uid: 14112a73-d723-48a4-b172-0bff7c3ed1ea
type: kubernetes.io/dockerconfigjson
[root@master ~]# kubectl get secrets harbor-auth
NAME TYPE DATA AGE
harbor-auth kubernetes.io/dockerconfigjson 1 2m23s
认证私有仓库
[root@master ~]# vim web2.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web2
spec:
imagePullSecrets: # 引用secret数据
- name: harbor-auth # 资源对象名称
containers:
- name: apache
image: harbor:443/myimg/httpd:latest # 使用私有仓库里的镜像
[root@master ~]# kubectl apply -f web2.yaml
pod/web2 created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web1 2/2 Running 0 46m
web2 1/1 Running 0 5s
emptyDir
本质是一个空目录
可以提供临时空间,同一个Pod中的容器也可以来共享数据
随着Pod创建而创建,Pod在该节点上运行期间,一直存在,当Pod被节点删除时,临时卷中的数据也会被永久删除
重启Pod不会造成emptyDir数据的丢失
临时空间
[root@master ~]# vim web2.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web2
spec:
imagePullSecrets:
- name: harbor-auth
volumes: # 卷配置
- name: cache # 卷名称,在容器内引用
emptyDir: {} # 资源类型
containers:
- name: apache
image: harbor:443/myimg/httpd:latest
volumeMounts: # 挂载卷
- name: cache # 卷名称
mountPath: /var/cache # 路径如果不存在,就创建出来,如果存在,就覆盖
[root@master ~]# kubectl apply -f web2.yaml
pod/web2 created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web1 2/2 Running 0 58m
web2 1/1 Running 0 8s
[root@master ~]# kubectl exec -it web2 -- bash
[root@web2 html]# mount | grep cache
/dev/sda1 on /var/cache type ext4 (rw,relatime)
更多推荐

所有评论(0)