K8S入门知识概念

天大地大妈咪最大 提交于 2021-02-03 06:40:34

1.查看节点的日志信息:journalctl -u kubelet -n 1000  

2.查看对应deployment的pod数量,并对其进行设置:kubectl get deployments & kubectl scale deployment nginx-deployment --replicas

3.node节点加入k8s集群:kubeadm join --token 1f627e.a37793601a406d7e 10.0.1.22:6443 --discovery-token-ca-cert-hash sha256:e12a8e1d1be7d308dad31bebdb2684d9d4ba7e5ae290f4fd1f855089b1abe71a    

4.K8S给node设置污点策略:

kubectl taint nodes node1 key=value:NoSchedule --新的不能容忍的pod不能再调度过来,但是老的运行在node上不受影响

kubectl taint nodes node1 key=value:NoExecute --新的不能容忍的pod不能调度过来,老的pod也会被驱逐

kubectl taint nodes node1 key=value:PreferNoSchedule --pod会尝试将pod分配到该节点

5.K8S如何给节点去除对应的污点:kubectl taint nodes master key:NoExecute-

6.重启kubeletsystemctl restart kubelet.service  

7.设置kubelet开机自启动:systemctl enable kubelet.service  

8.查看k8s存在的命名空间:kubectl get namespaces

9.查看命名空间里的服务:kubectl get services --namespace=logging

10.查看系统中所运行的容器:kubectl get po -n kube-system -o wide

11.查看对应的错误日志:kubectl describe pod XXX -n kube-system 

12.K8S的pod调度策略:

可以参考链接详细学习:https://www.qikqiak.com/post/kubernetes-affinity-scheduler/

nodeSelector调度:强制调度pod到某个节点上

亲和性和反亲和性调度:

nodeAffinity(节点亲和性)、podAffinity(pod 亲和性) 以及 podAntiAffinity(pod 反亲和性)

亲和性调度可以分成软策略硬策略两种方式:

  • 软策略就是如果你没有满足调度要求的节点的话,pod 就会忽略这条规则,继续完成调度过程,说白了就是满足条件最好了,没有的话也无所谓了的策略
  • 硬策略就比较强硬了,如果没有满足条件的节点的话,就不断重试直到满足条件为止,简单说就是你必须满足我的要求,不然我就不干的策略。

对于亲和性和反亲和性都有这两种规则可以设置: preferredDuringSchedulingIgnoredDuringExecutionrequiredDuringSchedulingIgnoredDuringExecution,前面的就是软策略,后面的就是硬策略。

affinity:

        nodeAffinity:

          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略

            nodeSelectorTerms:

            - matchExpressions:

              - key: kubernetes.io/hostname

                operator: NotIn

                values:

                - node03

          preferredDuringSchedulingIgnoredDuringExecution:  # 软策略

          - weight: 1

            preference:

              matchExpressions:

              - key: com

                operator: In

                values:

                - youdianzhishi

nodeSelectorTerms属性类型

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值大于某个值
  • Lt:label 的值小于某个值
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

如果nodeSelectorTerms下面有多个选项的话,满足任何一个条件就可以了;如果matchExpressions有多个选项的话,则必须同时满足这些条件才能正常调度 POD。

13.k8s pod erro exit code 137 该错误码表示node节点的内存不足

14.开启代理协议端口:kubectl  proxy --address='192.168.30.30' --port=8888 --accept-hosts='^*$' &

15.K8s中yaml的资源类型(kind字段)

工作负载型资源对象(workload):POD,ReplicaSet,Deployment,StatefulSet,DaemonSet,Job,Cronjob ...
服务发现及均衡资源对象:Service,Ingress ...
配置与存储资源对象:Volume(存储卷),CSI(容器存储接口,可以扩展各种各样的第三方存储卷),ConfigMap,Secret,DownwardAPI
集群级资源:Namespace,Node,Role,ClusterRole,RoleBinding,ClusterRoleBinding
元数据型资源:HPA,PodTemplate,LimitRange

16.K8S中存储卷volume的类型

.本地存储

1,EmptyDir

如果在此目录中创建删除文件,都将对容器中的/data目录有影响,如果删除Pod,文件将全部删除,即使是在宿主机上创建的文件也是如此,在宿主机上删除容器则k8s会再自动创建一个容器,此时文件仍然存在。

2.HostDir

在宿主机上指定一个目录,挂载到Pod的容器中,其实跟上面的写法不尽相同,这里只截取不同的部分,当pod删除时,本地仍然保留文件

.网络数据卷(NFS)

1.NFS

如何加入NFS文件系统

# 安装nfs服务

[root@nfs01 ~]# yum install nfs-utils rpcbind

# 创建nfs挂载目录

[root@nfs01 ~]# mkdir /data/volums/data01/ -p

# 启动服务

[root@nfs01 ~]# systemctl start rpcbind

[root@nfs01 ~]# systemctl enable rpcbind

[root@nfs01 ~]# systemctl start nfs-server

[root@nfs01 ~]# systemctl enable nfs-server

# 配置nfs服务

[root@nfs01 ~]# cat /etc/exports

/data/volums/data01 *(async,insecure,no_root_squash,no_subtree_check,rw)

# 查看nfs状态

[root@nfs01 ~]# showmount -e 192.168.17.195

Export list for 192.168.17.195:

/data/volums/data01 192.168.17.0/24

注意:对应的节点需要安装客户端:yum install nfs-utils

采用nfc存储的yaml样例

spec:

  containers:

    - name: web

      image: nginx

      imagePullPolicy: Never        #如果已经有镜像,就不需要再拉取镜像

      ports:

        - name: web

          containerPort: 80

          hostPort: 80        #将容器的80端口映射到宿主机的80端口

      volumeMounts:

        - name : nfs        #指定名称必须与下面一致

          mountPath: "/usr/share/nginx/html"        #容器内的挂载点

  volumes:

    - name: nfs            #指定名称必须与上面一致

      nfs:            #nfs存储

        server: 192.168.30.32       #nfs服务器ip或是域名

        path: "/nfs-data"                #nfs服务器共享的目录

/test目录中创建index.html文件后,这个文件也将在容器中生效,当Pod删除时,文件不受影响,实现了数据持久化。

三. Persistent Volume(PV)和Persistent Volume Claim(PVC)

其实这两种数据卷也属于网络数据卷,单拎出来是因为我觉得这个比前面的数据卷要酷多了,有种大数据,云平台的意思,当用户要使用数据存储的时候他是否还需要知道是什么类型的数据存储,答案是不需要,用户只想要安全可靠的数据存储,而且实现起来很简单,管理员建立一个存储平台,用户按自己的需求消费就可以了

PersistentVolume (PV) 是外部存储系统中的一块存储空间,由管理员创建和维护。与 Volume 一样,PV 具有持久性,生命周期独立于 Pod。

PersistentVolumeClaim (PVC) 是对 PV 的申请 (Claim)。PVC 通常由普通用户创建和维护。需要为 Pod 分配存储资源时,用户可以创建一个 PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,Kubernetes 会查找并提供满足条件的 PV。

静态Pvc示例

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

  name: efk-pvc

  namespace: kube-system  #注意pvc所在的命名空间和所引用的pod需要在同一个

spec:

  accessModes:

    - ReadWriteMany

  resources:

    requests:

      storage: 2Gi

  storageClassName: efk-nfs

pod如何引用pvc

        volumeMounts:

        - name: elasticsearch-logging

          mountPath: /data

        env:

        - name: "NAMESPACE"

          valueFrom:

            fieldRef:

              fieldPath: metadata.namespace

      volumes:

      - name: elasticsearch-logging

        persistentVolumeClaim:

          claimName: efk-pvc

 

具体创建和使用参考:

https://blog.51cto.com/forall/2135152

 

动态pvc的使用

创建和使用参考链接:https://blog.51cto.com/goome/2423200

过程中遇到的问题

nfs-client-provisioner这个pod一直报错error retrieving resource lock default/fuseim.pri-ifs: Unauthorized

最后参考链接

https://github.com/kubernetes-incubator/external-storage/issues/953

把下面这段替换rbac.yaml文件就行,大概的原因是rbac分配给nfs-client的权限不够

kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:

  name: efs-provisioner-runnerrules:

  - apiGroups: [""]

    resources: ["persistentvolumes"]

    verbs: ["get", "list", "watch", "create", "delete"]

  - apiGroups: [""]

    resources: ["persistentvolumeclaims"]

    verbs: ["get", "list", "watch", "update"]

  - apiGroups: ["storage.k8s.io"]

    resources: ["storageclasses"]

    verbs: ["get", "list", "watch"]

  - apiGroups: [""]

    resources: ["events"]

    verbs: ["list", "watch", "create", "update", "patch"]

  - apiGroups: [""]

    resources: ["endpoints"]

    verbs: ["get", "list", "watch", "create", "update", "patch"]

不再需要再创建pod前先申请pvc然后再挂载进pod,可以通过在部署podyaml文件中采用StatefulSet

statefulset,可以翻译成有状态的设定.

deployment的对比

deployment部署创建的pod是无状态的,重新调度pod,pod名字hostname,启动pod顺序删除pod顺序都是随机的.deployment使用的是共享存储,所有pod共用一个存储卷.

statefulset部署创建的pod是有状态的,重新调度pod,pod名字hostname保持固定不变,启动pod顺序删除pod顺序都可以根据定义的顺序有序执行操作,有序的动态更新,statefulset使用的存储,不是共用一个存储卷,一个pod对应一个存储卷(pv).pod重新创建调度挂载的存储卷保持不变.

 

apiVersion: apps/v1

kind: StatefulSet

metadata:

  name: statefulset-testspec:

  serviceName: headless-svc

  replicas: 3

  selector:

    matchLabels:

      app: headless-pod

  template:

    metadata:

      labels:

        app: headless-pod

    spec:

      containers:

      - image: httpd

        name: myhttpd

        ports:

        - containerPort: 80

          name: httpd

        volumeMounts:

        - mountPath: /mnt

          name: test

  volumeClaimTemplates:

  - metadata:

      name: test

      annotations:

        volume.beta.kubernetes.io/storage-class: managed-nfs-storage

    spec:

      accessModes: [ "ReadWriteOnce" ]

      resources:

        requests:

          storage: 100Mi

 

accessModes

用于定义资源的访问方式,受限于存储底层的支持,访问方式包括以下几种:

ReadWriteOnce – 被单个节点mount为读写rw模式

ReadOnlyMany – 被多个节点mount为只读ro模式

ReadWriteMany – 被多个节点mount为读写rw模式

 

17.K8S进入pod中:kubectl exec -ti curl-6bf6db5c4f-hm96f  -n default  -- /bin/sh

18.K8S的service介绍

service是一个抽象概念,定义了一个服务的多个pod逻辑合集和访问pod的策略,一般把service称为微服务

 

服务类型

ClusterIP

分配一个内部集群IP地址,只能在集群内部访问(同Namespace内的Pod),默认ServiceType

Service对象在Cluster IP range池中分配到的IP只能在内部访问,如果服务作为一个应用程序内部的层次,还是很合适的。如果这个Service作为前端服务,准备为集群外的客户提供业务,我们就需要给这个服务提供公共IP了。

 

NodePort

分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务,可以在集群外部访问。

访问地址:<NodeIP>:<NodePort>

 

LoadBalancer

分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务。

除此之外,Kubernetes会请求底层云平台上的负载均衡器,将每个Node[NodeIP]:[NodePort])作为后端添加进去。

 

service的类型

ClusterIP          默认模式,只能在集群内部访问

NodePort        在每个节点上都监听一个同样的端口号(30000-32767)ClusterIP和路由规则会自动创建。集群外部可以访问<NodeIP>:<NodePort>联系到集群内部服务,可以配合外部负载均衡使用(我现在公司用的就是这个模式配合阿里云的SLB

LoadBalancer     要配合支持公有云负载均衡使用比如GCEAWS。其实也是NodePort,只不过会把<NodeIP>:<NodePort>自动添加到公有云的负载均衡当中

ExternalName    创建一个dns别名指到service name上,主要是防止service name发生变化,要配合dns插件使用用户可以指定一个任意的名字,作为该service被解析的CNAME,这种类型的servcie不用指定clusterIP,因此kube-proxy不会管理这类service,这类service需要使用1.7版本以上的kubedns。比如用户想创建一个service,但要让所有容器访问该service的请求都引导到用户自己定义的外部域名服务,就可以通过这个方式实现。可以说这个是最自由的一个方式:你希望服务被如何解析,服务就能被如何解析。你甚至可以给多个service配置同一个externalName。

---

kind: Service

apiVersion: v1

metadata:

  name: mysql-5-7-01-service

spec:

  type: ExternalName

  externalName: ai-production-mysql-bot.cfyipcsxzevb.rds.cn-northwest-1.amazonaws.com.cn

---

通过上面创建的servicename去访问对应的aws上的mysql服务

 

集群中容器访问集群外部服务

DNS

Service type:ExternalName

Docker环境中,由于Docker Engine自带 DNS Server,我们使用容器名来访问其它容器,因为容器是不稳定的,当容器宕掉,再重新启动相同镜像的容器,IP地址会改变,所以我们不使用IP访问其它容器;同样的,在Kubernetes集群中,由于我们使用 kube-DNS,我们常用Service名称来访问某个服务,Service资源对象能保证其背后的容器副本始终是最新的IP

 

因此,我们可以利用这个特性,对Service名称和外部服务地址做一个映射,使之访问Service名称既是访问外部服务。例如下面的例子是将 svc1 xxx.xxx.xxx.xxx 做了对等关系。

 

kind: Service

apiVersion: v1

metadata:

  name: svc1

  namespace: default

spec:

  type: ExternalName

  externalName: somedomain.org

 

设置 Service EndPoint

Kubernetes集群中,同一个微服务的不同副本会对集群内或集群外(取决于服务对外暴露类型)暴露统一的服务名称,一个服务背后是多个 EndPointEndPoint解决映射到某个容器的问题,在 EndPoint 中不仅可以指定集群内容器的IP,还可以指定集群外的IP,我们可以利用这个特性使用集群外部的服务。

 

EndPoint 方式的缺点是只能指定IP,不能使用网址,比如网址,比如RDS的地址,这种情况下只能使用ExternalName来解决。

 

apiVersion: v1

kind: Service

metadata:

  name: mysql-production

spec:

  ports:

    - port: 3306

---

kind: Endpoints

apiVersion: v1

metadata:

  name: mysql-production

  namespace: default

subsets:

  - addresses:

      - ip: 192.168.1.25

    ports:

      - port: 3306

总结

本文介绍了集群内部访问外部服务的两种方法,ExternalName 类型的服务适用于外部服务使用域名的方式,缺点是不能指定端口;而EndPoint的方式适合于外部服务是IP的情况,但是可以指定端口。根据需要使用吧!

 

19. K8S中pod的内存和cpu设置

下面是如何给一个pod分配cpu和内存

Kubernetes系统上,l个单位的CPU相当于虚拟机上的l颗虚拟CPU(vCPU)或物理机上的一个超线程(Hyperthread,或称为一个逻辑CPU),它支持分数计量方式,一个核心(1core)相当于1000个微核心(millicores),因此500m相当于是0.5个核心

memory-request-limit.yaml 

apiVersion: v1

kind: Pod

metadata:

  name: memory-demo

spec:

  containers:

  - name: memory-demo-ctr

    image: vish/stress

    resources:

      limits:

        memory: "200Mi"

      requests:

        memory: "100Mi"

    args:

    - -mem-total

    - 150Mi

    - -mem-alloc-size

    - 10Mi

    - -mem-alloc-sleep

- 1s

超出容器的内存限制报错

NAME            READY     STATUS      RESTARTS   AGE

memory-demo-2   0/1       OOMKilled   1          24s

配置超出节点能力范围的内存申请pod会一直处于pending状态

kubectl get pod memory-demo-3 --namespace=mem-example

NAME            READY     STATUS    RESTARTS   AGE

memory-demo-3   0/1       Pending   0          25s

查看具体报错信息如下

Events:

  ...  Reason            Message

       ------            -------

  ...  FailedScheduling  No nodes are available that match all of the following predicates:: Insufficient memory (3).

 

 

如果不配置内存限制

如果不给容器配置内存限制,那下面的任意一种情况可能会出现:

容器使用内存资源没有上限,容器可以使用当前节点上所有可用的内存资源。

容器所运行的命名空间有默认内存限制,容器会自动继承默认的限制。

内存申请和限制的原因

通过配置容器的内存申请和限制,你可以更加有效充分的使用集群里内存资源。配置较少的内存申请, 可以让Pod跟任意被调度。设置超过内存申请的限制,可以达到以下效果:

Pod可以在负载高峰时更加充分利用内存。

可以将Pod的内存使用限制在比较合理的范围。

 

20. 强制删除pod:  kubectl delete po <your-pod-name> -n <name-space> --force --grace-period=0

21. K8S的镜像拉取策略

Always 总是拉取镜像

IfNotPresent 本地有则使用本地镜像,不拉取

Never 只使用本地镜像,从不拉取,即使本地没有

如果省略imagePullPolicy 镜像tag为 :latest 策略为always ,否则 策略为 IfNotPresent

 

22. Pod健康检测机制

对于Pod的健康状态检测,kubernetes提供了两类探针(Probe)来执行对Pod的健康状态检测:

  • LivenessProbe探针:
    用于判断容器是否存活,即Pod是否为running状态,如果LivenessProbe探针探测到容器不健康,则kubelet将kill掉容器,并根据容器的重启策略是否重启,如果一个容器不包含LivenessProbe探针,则Kubelet认为容器的LivenessProbe探针的返回值永远成功。
  • ReadinessProbe探针:
    用于判断容器是否启动完成,即容器的Ready是否为True,可以接收请求,如果ReadinessProbe探测失败,则容器的Ready将为False,控制器将此Pod的Endpoint从对应的service的Endpoint列表中移除,从此不再将任何请求调度此Pod上,直到下次探测成功。

每类探针都支持三种探测方法:

  • exec:通过执行命令来检查服务是否正常,针对复杂检测或无HTTP接口的服务,命令返回值为0则表示容器健康。
  • httpGet:通过发送http请求检查服务是否正常,返回200-399状态码则表明容器健康。
  • tcpSocket:通过容器的IP和Port执行TCP检查,如果能够建立TCP连接,则表明容器健康。

探针探测的结果有以下三者之一:

    • Success:Container通过了检查。
    • Failure:Container未通过检查。
    • Unknown:未能执行检查,因此不采取任何措施。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!