K8S-集群管理

目录

一、pod资源限制(resources)

二、重启策略(restartPolicy)

三、扩容缩容

1.手动扩容

2.自动扩容

2.1、数据采集组件

2.1.1、部署

2.2、HPA

2.2.1、案例

2.2.1.1、HPA基于cpu自动扩缩容

2.2.1.2、HPA基于内存自动扩缩容

2.3、cluster-autoscaler

二、使用步骤

1.引入库

2.读入数据

总结



一、pod资源限制(resources)

        当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。最常见的可设定资源是 CPU 和 内存大小 ,以及其他类型的资源。

        当为 Pod 中的容器指定了 request 资源时,调度器就使用该信息来决定将 Pod 调度到哪个节点上。当还为容器指定了 limit 资源时,kubelet 就会确保运行的容器不会使用超出所设的 limit 资源量。kubelet 还会为容器预留所设的 request 资源量,供该容器使用。

        如果 Pod 运行所在的节点具有足够的可用资源,容器可以使用超出所设置的 request 资源量。不过,容器不可以使用超出所设置的 limit 资源量。

        如果给容器设置了内存的 limit 值,但未设置内存的 request 值,Kubernetes 会自动为其设置与内存 limit 相匹配的 request 值。类似的,如果给容器设置了 CPU 的 limit 值但未设置 CPU 的 request 值,则 Kubernetes 自动为其设置 CPU 的 request 值 并使之与 CPU 的 limit 值匹配。

        官网示例:https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

  • Pod 和 容器 的资源请求和限制
spec.containers[].resources.requests.cpu		//定义创建容器时预分配的CPU资源
spec.containers[].resources.requests.memory		//定义创建容器时预分配的内存资源
spec.containers[].resources.limits.cpu			//定义cpu的资源上限 
spec.containers[].resources.limits.memory		//定义内存的资源上限
  •  案例
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

—CPU 资源单位:Kubernetes 中的一个 cpu 相当于1个 vCPU(1个超线程)。Kubernetes 也支持带小数 CPU 的请求。spec.containers[].resources.requests.cpu 为 0.5 的容器能够获得一个 cpu 的一半 CPU 资源(类似于Cgroup对CPU资源的时间分片)。表达式 0.1 等价于表达式 100m(毫核),表示每 1000 毫秒内容器可以使用的 CPU 时间总量为 0.1*1000 毫秒。

—内存资源单位:内存以字节为单位。可以以整数表示,或者以10为底数的指数的单位(E、P、T、G、M、K)来表示, 或者以2为底数的指数的单位(Ei、Pi、Ti、Gi、Mi、Ki)来表示。
 

二、重启策略(restartPolicy)

重启策略:Pod在遇到故障之后重启的动作

spec.Always:当容器终止退出后,总是重启容器,默认策略
spec.OnFailure:当容器异常退出(退出状态码非0)时,重启容器;正常退出则不重启容器
spec.Never:当容器终止退出,从不重启容器。

三、扩容缩容

1.手动扩容

        在生产环境下,在面临服务需要扩容的场景时,可以使用Deployment/RC的Scale机制来实现。

        slace扩容或缩容 Deployment、ReplicaSet、Replication Controller或 Job 中Pod数量。

Kubernetes支持对Pod的手动扩容和自动扩容。replicas决定了集群pod的数量。

  • 创建一个单节点的web容器
kubectl apply -f apache.yaml
  • 在集群运行的过程中我们可以动态调整集群pod的数量
  • 修改服务配置,即时生效:
kubectl edit deployments.apps apache
  • scale命令,控制pod的数量
kubectl scale deployments.appse apache --replicas=3

2.自动扩容

2.1、数据采集组件

        metrics-server 是一个集群范围内的资源数据集和工具,同样的,metrics-server 也只是显示数据,并不提供数据存储服务,主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、请求延时等指标,metric-server 收集数据给 k8s 集群内使用,如 kubectl,hpa,scheduler 等。不同k8s版本根据官网安装对应版本的metrics-server。

  •  github地址:https://github.com/kubernetes-sigs/metrics-server/

2.1.1、部署

  • 镜像下载
wget registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.6.4
  • 导入镜像
docker load -i metrics-server-0.6.4.tar.gz
  • 修改apiserver配置

注意:会中断业务,生产环境谨慎操作!这个是 k8s 在 1.17 的新特性,如果是 1.16 版本的可以不用添加,1.17 以后要添加。这个参数的作用是 Aggregation 允许在不修改 Kubernetes 核心代码的同时扩展 Kubernetes API。

vim /etc/kubernetes/manifests/kube-apiserver.yaml
22     - --enable-aggregator-routing=true               # 增加
  • 重启kubelet
systemctl restart kubelet
  • 部署metrics-server 服务

用到的yaml文件到github下载,地址:https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.1/components.yam

kubectl apply -f components.yaml
  • 验证
kubectl get pods -n kube-system | grep metrics

2.2、HPA

        kubernetes HPA(Horizontal Pod Autoscaling):根据监控指标(cpu 使用率、磁盘、自定义的等)自动扩容或缩容服务中的pod数量,当业务需求增加时,系统将无缝地自动增加适量 pod 容器,提高系统稳定性。hap监控容器资源的利用率。

        kubernetes KPA(Knative Pod Autoscaler):基于请求数对 Pod 自动扩缩容,KPA 的主要限制在于它不支持基于 CPU 的自动扩缩容。

        kubernetes VPA(Vertical Pod Autoscaler):基于 Pod 的资源使用情况自动设置 pod 的 CPU 和内存的 requests,从而让集群将 Pod 调度到有足够资源的最佳节点上。

  • HPA运作方式

        整体逻辑:K8s 的 HPA controller 已经实现了一套简单的自动扩缩容逻辑,默认情况下,每 15s 检测一次指标,只要检测到了配置 HPA 的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。同时,为了避免过于频繁的扩缩容,默认在 5min 内没有重新扩缩容的情况下,才会触发扩缩容。

  • 缺陷:

        HPA 本身的算法相对比较保守,可能并不适用于很多场景。例如,一个快速的流量突发场景,如果正处在 5min 内的 HPA 稳定期,这个时候根据 HPA 的策略,会导致无法扩容。

  • pod数量计算方式

        通过现有 pods 的 CPU 使用率的平均值(计算方式是最近的 pod 使用量(最近一分钟的平均值,从 metrics-server 中获得)除以设定的每个 Pod 的 CPU 使用率限额)跟目标使用率进行比较,并且在扩容时,还要遵循预先设定的副本数限制:MinReplicas <= Replicas <= MaxReplicas。
        计算扩容后 Pod 的个数:sum(最近一分钟内某个 Pod 的 CPU 使用率的平均值)/CPU 使用上限的整数+1

HPA官网:  Pod 水平自动扩缩 | Kubernetes

2.2.1、案例

  • 输出nginx服务yaml文件
kubectl -n jy-test create deployment nginx-web --image=harbortest.szjs.gov.cn/zjj-public/nginx:1.22.1-arm --dry-run=client -o yaml > nginx-web.yaml

        为了平常使用yaml时,由于手抖,造成的格式错误,建议尽量使用–dry-run参数来生成一个基础的yaml,再修改。

  • 通过yaml文件创建deployment
kubectl apply -f nginx-web.yaml
  • 对外暴露端口号
kubectl -n jy-test expose deployment nginx-web --port=80 --type=NodePort --target-port=80 --name=svc-nginx-web -o yaml >> nginx-web.yaml
  • 通过yaml文件创建service
kubectl apply -f nginx-web.yaml

配置资源限制

kubectl -n jy-test edit deploy nginx-web

    spec:
      containers:
      - image: harbortest.szjs.gov.cn/zjj-public/nginx:1.22.1-arm
        imagePullPolicy: IfNotPresent
        name: nginx
        resources:           # 注意:nginx 的 pod 里需要有如下字段,否则 hpa 会采集不到内存指标
          limits:
            cpu: 500m
            memory: 256Mi
          requests:
            cpu: 200m
            memory: 256Mi
2.2.1.1、HPA基于cpu自动扩缩容

        nginx-web 服务正在运行,使用 kubectl autoscale 创建自动缩放器,实现对 nginx-web 这个deployment 创建的 pod 自动扩缩容,下面的命令将会创建一个 HPA,HPA 将会根据 CPU资源指标增加或减少副本数,创建一个可以实现如下目的的 hpa:
(1)让副本数维持在 1-10 个之间(这里副本数指的是通过 deployment 部署的 pod 的副本数)
(2)将所有 Pod 的平均 CPU 使用率维持在 50%(通过 kubectl run 运行的每个 pod 如果是 200毫核,这意味着平均 CPU 利用率为 100 毫核)

  • 创建HPA基于cpu自动扩缩容
kubectl -n jy-test autoscale deployment nginx-web --cpu-percent=50 --min=1 --max=10 --name=nginx-web
  • 查看
 kubectl -n jy-test get hpa
  • 验证:重新打开一个master节点的终端,进行如下操作 
kubectl -n jy-test exec -it nginx-web-f646c4b44-nlxjq bash
/# for i in {1..500000}; do curl http://www.test.com/my_service &  done

        当容器的cpu占用超过 50% 的时候,自动扩展一个POD,依次扩展,一直到最大值,如果cpu访问不足 50% 的时候,每 300s 缩减一个 POD 节点,直到最小值时停止。

  • 查看  
kubectl -n jy-test get hpa
  • 可以看到cpu目标及当前状态,最大、最小、当前副本数。 

kubectl -n jy-test get pod

 K8S-集群管理_第1张图片

2.2.1.2、HPA基于内存自动扩缩容

        nginx 服务正在运行,使用 kubectl autoscale 创建自动缩放器,实现对 nginx 这个deployment 创建的 pod 自动扩缩容,下面的命令将会创建一个 HPA,HPA 将会根据内存资源指标增加或减少副本数,创建一个可以实现如下目的的 hpa:
(1)让副本数维持在 1-10 个之间(这里副本数指的是通过 deployment 部署的 pod 的副本数)
(2)将所有 Pod 的平均内存使用率维持在 60%

  •  创建HPA基于内存自动扩缩容,yaml文件如下

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-web-hpa2               # hpa的名称
  namespace: jy-test
spec:
  maxReplicas: 10
  metrics:
  - resource:
      name: memory
      target:
        averageUtilization: 60
        type: Utilization
    type: Resource
  minReplicas: 1
  scaleTargetRef:                   # 定义监视控制器,需要扩容缩谷时需要通知的控制器
    apiVersion: apps/v1          
    kind: Deployment
    name: nginx-web                 # 控制器的名称
  • 创建
kubectl create -f hpa.yaml
  • 查看
kubectl -n jy-test get hpa
  • 可以看到当前内存使用率、目标内存使用率,最大、最小、当前副本数 

2.3、cluster-autoscaler

        Cluster Autoscaler (CA)是一个独立程序,是用来弹性伸缩 kubernetes 集群的。它可以自动根据部署应用所请求的资源量来动态的伸缩集群。当集群容量不足时,它会自动去 Cloud Provider (支持GCE、GKE 和 AWS)创建新的 Node,而在 Node 长时间资源利用率很低时自动将其删除以节省开支。
项目地址:GitHub - kubernetes/autoscaler: Autoscaling components for Kubernetes

  • 在以下情况下,集群自动扩容或者缩放:

扩容:由于资源不足,某些 Pod 无法在任何当前节点上进行调度。
缩容: Node 节点资源利用率较低时,且此 node 节点上存在的 pod 都能被重新调度到其他 node节点上运行。

  • 在以下情况下,集群节点不会被 CA 删除

1、节点上有 pod 被 PodDisruptionBudget 控制器限制。
2、节点上有命名空间是 kube-system 的 pods。
3、节点上的 pod 不是被控制器创建,例如不是被 deployment, replica set, job, stateful set 创建。
4、节点上有 pod 使用了本地存储。
5、节点上 pod 驱逐后无处可去,即没有其他 node 能调度这个 pod。
6、节点有注解:“cluster-autoscaler.kubernetes.io/scale-down-disabled”: “true”(在 CA 1.0.3 或更高版本中受支持)。

  • 命令
 kubectl annotate node  cluster-autoscaler.kubernetes.io/scale-down-disabled=true
  • HPA 如何与 Cluster Autoscaler 一起使用?

        Horizontal Pod Autoscaler 会根据当前 CPU 负载更改部署或副本集的副本数。如果负载增加,则 HPA 将创建新的副本,集群中可能有足够的空间,也可能没有足够的空间。如果没有足够的资源,CA将尝试启动一些节点,以便 HPA 创建的 Pod 可以运行。如果负载减少,则 HPA 将停止某些副本。结果,某些节点可能变得利用率过低或完全为空,然后 CA 将终止这些不需要的节点。

四、service服务与负载均衡

1、Service 简介

        Kubernetes Service定义了这样一种抽象: Service是一种可以访问 Pod逻辑分组的策略, Service通常是通过 Label Selector访问 Pod组。

        Service能够提供负载均衡的能力,但是在使用上有以下限制:只提供 4 层负载均衡能力,而没有 7 层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的。

2.1、service的类型

2.1.1、ClusterIp

范围:默认类型,集群内部使用(master、node、pod)自动分配一个仅Cluster内部可以访问的虚拟IP(VIP),实现负载均衡和服务的发现。

场景:当发现某一个pod不能使用的时候RS会在其他机器上创建一个相同的pod,及其对应的容器。会变化的pod给我们访问带来非常多的不便,Service就是解决一个问题的方法。

2.1.2、NodePort(对外暴露应用)

        在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过NodeIP:NodePort访问来访问该服务。
端口范围:30000~32767

2.1.3、LoadBalancer(对外暴露应用,适用于公有云)

        在NodePort的基础上,借助Cloud Provider创建一个外部负载均衡器,并将请求转发到NodePort。

2.1.4、ExternalName

        创建一个dns别名指到service name上,主要是防止service name发生变化,要配合dns插件使用。通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容。这只有 Kubernetes 1.7或更高版本的kube-dns才支持。

2.2、Service 工作流程

  1. 客户端访问节点时通过 iptables实现的

  2. iptables规则是通过 kube-proxy写入的

  3. apiserver通过监控 kube-proxy去进行对服务和端点的监控

  4. kube-proxy通过 pod的标签( lables)去判断这个断点信息是否写入到 Endpoints里

​​​​​​​

  1. ClusterIP服务

  1. 理论点:

—Service会创建一个cluster ip,这个地址对应资源地址,不管pod如何变化,service总能找到对应的pod,且cluster ip 保持不变,如果pod对应多个容器,service会自动在多个容器间实现负载均衡。

—Service通过iptables/lvs规则将访问的请求最终映射到pod的容器内部服务上。

  1. service服务端口:

—portservice暴露在cluster ip上的端口,是提供给集群内部客户访问servie的入口,供集群内部服务访问使用。

—targetPort是pod上容器服务监听的端口,从port或nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort进入容器,从而达到访问pod容器内部服务的目的。

  1. 服务的自动发现:

创建服务:kubectl  apply  -f  资源文件

查询服务:kubectl  get  service

查询IP池:ipvsadm -L -n        

—Cluster IP是集群分配的服务IP,供集群访问,在集群内部也可以通过服务名称访问,服务的名称是通过coredns解析的,每个服务在创建的过程中都会完成自动注册。

服务名称:<服务名称>.<名称空间>.srv.cluser.local【容器内部可以使用】

服务缩写:服务名称

  1. 访问服务:集群内可以直接访问服务,但集群外无法访问服务
  2. 服务原理

代理模式:v1.0用户空间;v1.1 iptables代理;v1.8 ipvs代理,如果不满足条件退回至v1.1。

  1. kube-proxy介绍:是daemonsets.apps的资源类型,查询ipvsadm-save -n,按标签查找pod,lvs规则为能手动改,定义轮询规则。

kube-proxy是实现kubernetes Service的通信与负载均衡机制的重要组件,是Kubernetes的核心组件。

  1. Cluster IP服务会有标签,和pod的标签一致,kube-proxy是通过标签跟踪到IP的。

  1. 操作案例:

vim clusterip.yaml         #注:多个资源可以写到同一个yaml文件中,使用---分割。   

---

kind: Service          #定义资源类型

apiVersion: v1         #资源版本

metadata:

  name: myapache       #服务的名称

spec:                  #服务的详细信息

  ports:               #端口定义

  - protocol: TCP      #服务协议

    port: 80           #监听端口,开放前端的访问端口,是service的端口

    targetPort: 80     #容器的端口

  selector:            #选择为那个deployment提供服务(后端)

    myapp: httpd       # 标签必须与容器中一致,kubectl get pod --show-labels查看

  type: ClusterIP      #服务类型

kubectl apply -f clusterip.yaml           #记载资源文件,创建新的IP。

kubectl get service                   #查询服务,可以通过该命令查看到集群中不变的clusterIP

ipvsadm --save                         #查看配置的规则

kubectl exec -it mypod -- /bin/bash       #进去集群内部

curl http://clusterIP/                 #查看是否可以联通其他的集群,clusterIP为之前查到的。

#注:此时即使增加集群中节点的数量,服务也会是扩展。

    1. NodePort服务
  1. 理论点:
  1. 作用:范围四层发布服务,通过node上的ip和端口,对集群外发布服务
  2. 为了使的集群的内部和外部连接起来,利用端口映射实现相互访问,此时使用nodePort服务,基于端口对外提供服务(四层)。

-LoadBalancer:使用外部的云服务(需要支持,externallPs),使用云提供商的负载局衡器(云容器引擎CCE)

-nodeport:基于端口对外提供服务(四层),优点,可以发布任何服务,性能更好,没有七层的功能。nodeport==clusterIP+IPtables

-lngress使用ingress控制器(七层),只支持http协议,和nodeport区别,就类似于nginx和lvs的区别

  1. 服务本质是:LVS+iptables
  1. 操作案例:

ipvsadm -L -n                             #查LVS的规则

vim mynodeport.yaml

---

kind: Service

apiVersion: v1

metadata:

  name: mynodeport

spec:

  ports:

  - protocol: TCP

    port: 80

    targetPort: 80

  selector:

    myapp: httpd

  type: NodePort                       #指定服务类型

kubectl apply -f mynodeport.yaml          #记载资源文件

kubectl  get service  -o wide             #查看对外共享的端口

curl  http://节点IP:查看到的端口号        #在同一局域网查看提供的服务,查看能否联通

    1. headless服务
  1. 理论点:
  1. 作用:无头服务,有时候不需要或者不想要负载均衡,以及单独的service IP。遇到这种情况,我们可以创建Headless服务。
  2. Headless服务会把IP通过多个A记录的形式解析到具体的容器IP上面,多用于有状态的服务。
  3. 本质是lvs+iptables,工作在四层。
  1. 操作案例:

vim myheadless.yaml

---

kind: Service

apiVersion: v1

metadata:

  name: myheadless

spec:

  ports:

  - protocol: TCP

    port: 80

    targetPort: 80

  selector:

    myapp: httpd

  type: ClusterIP

  clusterIP: None      # 新添加,重点

kubectl apply -f myheadless.yaml              #加载配置文件

kubectl get service                           #查看service服务的内容

kubectl exec -it mypod -- /bin/bash               #进入到mypod集群中

yum install -y bind-utils                     #安装提供host命令的软件

host myheadless.default.svc.cluster.local     #查看集群中容器有哪些,以及集群的IP

    1. ingress插件
  1. 理论点:
  1. ingress本质是一台nginx,公开了从集群外部到集群内services路由,类似于反向代理的功能。
  2. ingress是外部容器,七层服务,可以配置域名,不同的域名配置不同的服务,它的后端一定是服务。
  3. Ingress是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
  4. Ingress可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
  5. 服务本质:nginx/haproxy
  1. 操作案例:
  1. 安装控制器:(master主机)

docker load -i ingress-nginx.tar.gz                                                   #导入镜像

docker tag quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0 192.168.1.100:5000/nginx-ingress-controller:0.30.03                                                                #为镜像打标签

docker push 192.168.1.100:5000/nginx-ingress-controller:0.30.0                    #将镜像上传至私有仓库

curl http://192.168.1.100:5000/v2/nginx-ingress-controller/tags/list              #查看是否上传成功

vim ingress/mandatory.yaml        #更改资源文件

221:  image: 192.168.1.100:5000/nginx-ingress-controller:0.30.0

kubectl apply -f ingress/mandatory.yaml       #加载资源文件

kubectl -n ingress-nginx get pod              #查看控制器是否创建成功

  1. 发布任务:

vim ingress-example.yaml      #编写资源文件

---

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: my-web

  annotations:

    kubernetes.io/ingress.class: "nginx"        #这个注释是找nginx类别

spec:                                       

  backend:                                      #转发的目的地,叫后端

    serviceName: myapache                       #定义后端服务的名称

servicePort: 80                            #定义服务的端口号 

kubectl apply -f ingress-example.yaml

kubectl get ingresses                        #查看释放node节点IP,然后给IP绑定弹性公网IP,就完成了对外发布服务

curl http://192.168.1.33/info.php

    1. metrics资源利用率监控
  1. 理论点:
  1. 监控容器使用插件是metricsˈmetriks灭缺死可以监控node节点上的cpu、内存的使用率,或者pod对资源的占用率,通过对资源占用的了解,可以更加合理的部署容器应用。
  2. metrics从k8s 1.8开始,资源使用情况的监控可以通过metrics API的形式获取,具体的组件为matrics server,用来替换之前的heapster,heapster从1.11开始逐渐被废弃。
  3. 需要依靠聚合路由
  4. kubelet的资源文件/var/lib/kubelet/cofig.yaml:yaml资源文件要写pod类型,放在/etc/kubernetes/manifests/
  5. kubectl top nodes指令中top会直接从etcd里去查看数据。
  1. 操作案例:
  1. 开启apiserver聚合服务:默认K8S不支持聚合服务就没法用metrics,这里首先需要修改配置文件开启该功能。

vim /etc/kubernetes/manifests/kube-apiserver.yaml          #如果配置文件出错,kubectl启动不了

- --enable-aggregator-routing=true                  # spec.containers.command 最下面手动添加如下一行,聚合路由参数

systemctl restart kubelet                                  #重启服务

kubectl -n kube-system get pod kube-apiserver-master -o yaml |grep enable-aggregator-routing      #查看静态路由是否启动

  1. kubelet证书的申请与签发:要在所有节点执行

vim /var/lib/kubelet/config.yaml

serverTLSBootstrap: true   #在master主机最后追加

for i in  31 32 33                #在跳板机上执行以下命令

do

ssh 192.168.1.$i "echo 'serverTLSBootstrap: true' >> /var/lib/kubelet/config.yaml"     #节点向master服务器要证书。

ssh 192.168.1.$i "systemctl restart kubelet"      #重启服务

done

systemctl restart kubelet

kubectl get certificatesigningrequests             #查看证书是否签发成功,所有证书状态都是Approved(已经被签发了)

kubectl certificate approve csr-wsfz7              #如果是pending状态,重新签发证书,将所有要签发的证书签发

kubectl delete certificatesigningrequests 证书名称   #删除申请的多余证书

  1. 安装mertics插件:拷贝云盘的kubernetes/v1.17.6/metrics 目录到 master 上

docker load -i metrisc-server.tar.gz

docker tag gcr.io/k8s-staging-metrics-server/metrics-server:master 192.168.1.100:5000/metrics-server:master

docker push 192.168.1.100:5000/metrics-server:master

vim deployment.yaml   #修改主进程文件

29: image: 192.168.1.100:5000/metrics-server:master

kubectl apply -f rbac.yaml -f pdb.yaml -f deployment.yaml -f service.yaml -f apiservice.yaml 

  1. master主机上查询验证

kubectl -n kube-system get pod               #验证pod

kubectl -n kube-system get apiservices       #验证API

kubectl top node                             #查看节点的资源

kubectl top pod                             #查看pod占用资源的情况。

  1. 安装metrics-server(在master主机操作)

需要下载的官网:https://github.com/kubernetes-sigs/metrics-server

rbac.yaml :授权控制器

pdb.yaml :中断控制器

deployment.yaml :主进程metrics(修改镜像地址)

service.yaml :后端是metics主进程的服务

apiservice.yaml:注册集群API

  1. 测试:

kubectl apply -f myapache.yaml

kubectl  get  pod

kubectl  exec  -it  节点名称  --  /bin/bash   #进入容器中

while 0                                       #写一个死循环

do

echo “hello word”

done

kubectl top pod        #重新开启一个终端,连接master管理节点,查看pod的资源。

kubectl top node       #重新开启一个终端,连接master管理节点,查看节点的资源利用。

补充:1cup=1000m

 1、kube-proxy简介

        kube-proxy负责为Service提供cluster内部的服务发现和负载均衡,它运行在每个Node计算节点上,负责Pod网络代理, 它会定时从etcd服务获取到service信息来做相应的策略,维护网络规则和四层负载均衡工作。在K8s集群中微服务的负载均衡是由Kube-proxy实现的,它是K8s集群内部的负载均衡器,也是一个分布式代理服务器,在K8s的每个节点上都有一个,这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的Kube-proxy就越多,高可用节点也随之增多。

        service是一组pod的服务抽象,相当于一组pod的负载均衡,负责将请求分发给对应的pod。service会为这个负载均衡提供一个IP,一般称为cluster IP。kube-proxy的作用主要是负责service的实现,具体来说,就是实现了内部从pod到service和外部的从node port向service的访问。

  • kube-proxy其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。
  • kube-proxy管理sevice的Endpoints,该service对外暴露一个Virtual IP,也成为Cluster IP, 集群内通过访问这个Cluster IP:Port就能访问到集群内对应的serivce下的Pod。
  • service是通过Selector选择的一组Pods的服务抽象,其实就是一个微服务,提供了服务的LB和反向代理的能力,而kube-proxy的主要作用就是负责service的实现。
  • service另外一个重要作用是,一个服务后端的Pods可能会随着生存灭亡而发生IP的改变,service的出现,给服务提供了一个固定的IP,而无视后端Endpoint的变化。

 3、Endpoints简介

        endpoint是k8s集群中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址。service配置selector,endpoint controller才会自动创建对应的endpoint对象;否则,不会生成endpoint对象。

3.1、工作流程

        一个 Service 由一组 backend Pod 组成。这些 Pod 通过 endpoints 暴露出来。 Service Selector 将持续评估,结果被 POST 到一个名称为 Service-hello 的 Endpoint 对象上。 当 Pod 终止后,它会自动从 Endpoint 中移除,新的能够匹配上 Service Selector 的 Pod 将自动地被添加到 Endpoint 中。 检查该 Endpoint,注意到 IP 地址与创建的 Pod 是相同的。现在,能够从集群中任意节点上使用 curl 命令请求 hello Service :

3.2、示例:service-hello.yaml

        【例如】k8s集群中创建一个名为hello的service,就会生成一个同名的endpoint对象,ENDPOINTS就是service关联的pod的ip地址和端口。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 3
  selector:
    matchLabels:
     run: hello
  template:
    metadata:
      labels:
        run: hello
    spec:
      containers:
      - name: nginx
        image: nginx:latest
---
apiVersion: v1
kind: Service
metadata:
  name: service-hello
  labels:
  name: service-hello
spec:
  type: NodePort      # 这里代表是NodePort类型的,另外还有ingress,LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    nodePort: 31111   # 所有的节点都会开放此端口30000--32767,此端口供外部调用。
  selector:
    run: hello

3.2.1、查看验证

        Kube-proxy进程获取每个Service的Endpoints,实现Service的负载均衡功能。

[root@master ~]# kubectl get pods -o wide 
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
hello-688d6b8d4c-bzfj9   1/1     Running   0          21m   10.254.1.2   node01              
hello-688d6b8d4c-nwgd6   1/1     Running   0          21m   10.254.2.2   node02              
hello-688d6b8d4c-s5ff8   1/1     Running   0          21m   10.254.3.2   harbor              

[root@master ~]# kubectl get service service-hello -o wide 
NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE   SELECTOR
service-hello   NodePort   10.244.143.216           80:31111/TCP   18h   run=hello

[root@master ~]# kubectl describe service service-hello 
Name:                     service-hello
Namespace:                default
Labels:                   
Annotations:              
Selector:                 run=hello
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.244.143.216
IPs:                      10.244.143.216
Port:                       80/TCP
TargetPort:               8080/TCP
NodePort:                   31111/TCP
Endpoints:                10.254.1.6:8080,10.254.2.3:8080,10.254.3.3:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   

[root@master ~]# kubectl get endpoints service-hello 
NAME            ENDPOINTS                                         AGE
service-hello   10.254.1.6:8080,10.254.2.3:8080,10.254.3.3:8080   18h

        Service的负载均衡转发规则:访问Service的请求,不论是Cluster IP+TargetPort的方式;还是用Node节点IP+NodePort的方式,都被Node节点的Iptables规则重定向到Kube-proxy监听Service服务代理端口。kube-proxy接收到Service的访问请求后,根据负载策略,转发到后端的Pod。

3、kubernetes中的port

  • nodePort是外部访问k8s集群中service的端口,通过nodeIP: nodePort可以从外部访问到某个service。
  • port是k8s集群内部访问service的端口,即通过clusterIP: port可以访问到某个service。
  • targetPort是pod的端口,从port和nodePort来的流量经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
  • containerPort是pod内部容器的端口,targetPort映射到containerPort。

4、kubernetes服务发现

Kubernetes提供了两种方式进行服务发现, 即环境变量和DNS, 简单说明如下:

环境变量:当你创建一个Pod的时候,kubelet会在该Pod中注入集群内所有Service的相关环境变量。【注意】要想一个Pod中注入某个Service的环境变量,则必须Service要比该Pod先创建。这一点,几乎使得这种方式进行服务发现不可用。

DNS:这是k8s官方强烈推荐的方式!!! 可以通过cluster add-on方式轻松的创建KubeDNS来对集群内的Service进行服务发现。

5、Service代理模式

5.1、userspace 代理模式

        这种模式,kube-proxy 会监视 Kubernetes 控制平面对 Service 对象和 Endpoints 对象的添加和移除操作。 对每个 Service,它会在本地 Node 上打开一个端口(随机选择)。 任何连接到“代理端口”的请求,都会被代理到 Service 的后端 Pods 中的某个上面(如 Endpoints 所报告的一样)。 使用哪个后端 Pod,是 kube-proxy 基于 SessionAffinity 来确定的。

        最后,它配置 iptables 规则,捕获到达该 Service 的 clusterIP(是虚拟 IP) 和 Port 的请求,并重定向到代理端口,代理端口再代理请求到后端Pod。

        默认情况下,用户空间模式下的 kube-proxy 通过轮转算法选择后端。

5.2、iptables 代理模式

        这种模式,kube-proxy 会监视 Kubernetes 控制节点对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会配置 iptables 规则,从而捕获到达该 Service 的 clusterIP 和端口的请求,进而将请求重定向到 Service 的一组后端中的某个 Pod 上面。 对于每个 Endpoints 对象,它也会配置 iptables 规则,这个规则会选择一个后端组合。

        默认的策略是,kube-proxy 在 iptables 模式下随机选择一个后端。

        使用 iptables 处理流量具有较低的系统开销,因为流量由 Linux netfilter 处理, 而无需在用户空间和内核空间之间切换。 这种方法也可能更可靠。

        如果 kube-proxy 在 iptables 模式下运行,并且所选的第一个 Pod 没有响应, 则连接失败。 这与用户空间模式不同:在这种情况下,kube-proxy 将检测到与第一个 Pod 的连接已失败, 并会自动使用其他后端 Pod 重试。

        你可以使用 Pod 就绪探测器 验证后端 Pod 可以正常工作,以便 iptables 模式下的 kube-proxy 仅看到测试正常的后端。 这样做意味着你避免将流量通过 kube-proxy 发送到已知已失败的 Pod。

[root@master ~]# vim mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    name: mysql
    role: service
  name: mysql-service
spec:
  ports:
    - port: 3306
      targetPort: 3306
      nodePort: 30964
  type: NodePort
  selector:
    mysql-service: "true"
    name: mysql

[root@master ~]# kubectl apply -f mysql-service.yaml 
service/mysql-service created

[root@master ~]# kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.244.0.1               443/TCP          29h
mysql-service   NodePort    10.244.140.208           3306:30964/TCP   19s
service-hello   NodePort    10.244.143.216           80:31111/TCP     20h

5.3、IPVS 代理模式

特性状态: Kubernetes v1.11 [stable]

        在 ipvs 模式下,kube-proxy 监视 Kubernetes 服务和端点,调用 netlink 接口相应地创建 IPVS 规则, 并定期将 IPVS 规则与 Kubernetes 服务和端点同步。 该控制循环可确保IPVS 状态与所需状态匹配。访问服务时,IPVS 将流量定向到后端Pod之一。

        IPVS代理模式基于类似于 iptables 模式的 netfilter 挂钩函数, 但是使用哈希表作为基础数据结构,并且在内核空间中工作。 这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。 与其他代理模式相比,IPVS 模式还支持更高的网络流量吞吐量。

IPVS 提供了更多选项来平衡后端 Pod 的流量。 这些是:

  • rr:轮替(Round-Robin)
  • lc:最少链接(Least Connection),即打开链接数量最少者优先
  • dh:目标地址哈希(Destination Hashing)
  • sh:源地址哈希(Source Hashing)
  • sed:最短预期延迟(Shortest Expected Delay)
  • nq:从不排队(Never Queue)

5.3.1、kube-proxy配置 ipvs模式(所有节点)

1)加载ip_vs相关内核模块

[root@master ~]# modprobe -- ip_vs
[root@master ~]# modprobe -- ip_vs_sh
[root@master ~]# modprobe -- ip_vs_rr
[root@master ~]# modprobe -- ip_vs_wrr
[root@master ~]# modprobe -- nf_conntrack_ipv4

[root@master ~]# lsmod | grep ip_vs
ip_vs_sh               12688  0 
ip_vs_wrr              12697  0 
ip_vs_rr               12600  0 
ip_vs                 141432  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          133053  10 ip_vs,nf_nat,nf_nat_ipv4,nf_nat_ipv6,xt_conntrack,nf_nat_masquerade_ipv4,nf_nat_masquerade_ipv6,nf_conntrack_netlink,nf_conntrack_ipv4,nf_conntrack_ipv6
libcrc32c              12644  4 xfs,ip_vs,nf_nat,nf_conntrack

2)安装ipvsadm工具

[root@master ~]# yum -y install ipset ipvsadm

3)查看kube-proxy 

[root@master ~]# kubectl get pod -n kube-system | grep kube-proxy
kube-proxy-2f9x9                 1/1     Running   2 (18h ago)   29h
kube-proxy-8xjdp                 1/1     Running   2 (18h ago)   29h
kube-proxy-f425c                 1/1     Running   2 (18h ago)   29h
kube-proxy-t4pq8                 1/1     Running   2 (18h ago)   29h

3)编辑kube-proxy配置文件,mode修改成ipvs 


[root@master ~]# kubectl edit configmaps -n kube-system kube-proxy 
mode: "ipvs" 

[root@master ~]# kubectl get pod -n kube-system | grep kube-proxy |awk '{system("kubectl delete pod "$1" -n kube-system")}'
pod "kube-proxy-2f9x9" deleted
pod "kube-proxy-8xjdp" deleted
pod "kube-proxy-f425c" deleted
pod "kube-proxy-t4pq8" deleted

[root@master ~]# kubectl get pod -n kube-system | grep kube-proxy       # 再次查看
kube-proxy-5p5tb                 1/1     Running   0              10s
kube-proxy-c2vxk                 1/1     Running   0              13s
kube-proxy-z2hjm                 1/1     Running   0              12s
kube-proxy-zgjc7                 1/1     Running   0              9s

[root@master ~]# ipvsadm -Ln

 说明:要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS 在节点上可用。当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。

6、服务状态

        从数据层面看状态,数据的状态往往受2个维度有关,一是与时间相关或者顺序相关的,不同的操作顺序可能导致同一个时间点上的数据状态大于1个,二是与数据的副本状态相关的。也就是数据的位置,数据落在多个副本上,可能出现多种数据状态的组合。

        从服务层面看,服务层面的状态取决于实例是单独维护数据还是共享数据,或者说是否存在多个数据闭环让数据的流向产生了多条路径。有状态的服务往往比较难进行水平拓展,在现在容器盛行的环境,把服务设计成无状态的更加高效,即便是有状态的服务,也要将状态内敛在系统的某个范围,比如分布式的存储,对于业务服务,我不需要关心数据在多个副本的状态,数据的状态由分布式存储这个服务本身解决。

差异维度 有状态服务 无状态服务
服务本身 服务本身依赖或者存在局部的状态数据,这些数据需要自身持久化或者可以通过其他节点恢复。 服务不依赖自身的状态,实例的状态数据可以维护在内存中。
节   点 一个请求只能被某个节点(或者同等状态下的节点)处理。 任何一个请求都可以被任意一个实例处理。
数据状态 存储状态数据,实例的拓展需要整个系统参与状态的迁移。 不存储状态数据,实例可以水平拓展,通过负载均衡将请求分发到各个节点。
系统中 在一个封闭的系统中,存在多个数据闭环,需要考虑这些闭环的数据一致性问题。 在一个封闭的系统中,只存在一个数据闭环。
架构中 通常存在于分布式架构中。 通常存在于单体架构的集群中。
相关资源

statefulSet,由于是有状态的服务,所以每个pod都有特定的名称和网络标识。比如pod名是由statefulSet名+有序的数字组成(0、1、2..)

ReplicaSet、ReplicationController、Deployment等,由于是无状态服务,所以这些控制器创建的pod序号都是随机值。并且在缩容的时候并不会明确缩容某一个pod,而是随机的,因为所有实例得到的返回值都是一样,所以缩容任何一个pod都可以。

相关服务 有状态服务 可以说是 需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysql数据库、kafka、zookeeper等) 多个实例可以共享相同的持久化数据。例如:nginx实例,tomcat实例等

 


你可能感兴趣的:(kubernetes,容器,云原生)