控制器

控制器是什么?
控制器是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)

更多推荐