Kubernetes权威指南一

一、Kubernetes入门

1.1了解kubernetes

     在每个Pod中都运行着一个特殊的被称为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume挂载卷,因此他们之间的通信和数据交换更为高校,在设计时候我们可以充分利用这一特性将一组密切相关的服务进程放入同一个Pod中。

      在集群管理方面,Kubernetes将集群分为一些Master节点,和一些Node节点,Master节点上部署了kube-apiservice,kube-conller-manager,kube-scheduler管理进程,这些进程实现了集群的资源管理,Pod调度,弹性伸缩,安全控制,系统监控和纠错等管理功能,并都是自动完成的。Node节点作为集群的工作节点,其上运行着真正的应用程序。在Node上,Kubernetes运行的最小单元是Pod。在Node节点上运行着kubelet、kube-proxy,这些服务进程负责Pod的创建,启动,监控,销毁,以及实现软件模式的负载均衡。

通过一个实例来理解Kuberentes

创建一个Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: mysql
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec: 
      containers:
      - image: mysql:5.7
        name: mysql
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"

创建一个Service

apiVersion: v1
kind: Service
metadata:
  name: mysql 
spec:
  ports:
  - port: 3306
  selector:
    app: mysql

创建一个Tomcate应用,最后的value为mysql Service的ClusterIP

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: myweb
  labels:
    app: myweb
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - image: tomcat-app:v1
        name: myweb
        ports:
        - containerPort: 8080
        env:
        - name: MYSQL_SERVICE_HOST
          value: 10.103.76.207

创建web的service

apiVersion: v1
kind: Service
metadata:
  name: myweb
spec:
  type: NodePort
  ports:
  - port: 8080
    nodePort: 30001
  selector:
    app: myweb

 1.4、Kubernetes基础概念

namespace的创建

apiVersion:  v1
kind: Namespace
metadata:
  name:  develoyment

通过文件创建以后,namespace就永久存在了。

1.4.3 应用类

    Kubernetes 里的 Service 具有一个全局唯 的虚拟 ClusterIP 地址 Service 一旦被创建, Kubernetes 就会 动为它分配一个可用的 lusterIP 地址,而且在 Service 整个生命周期中,它的 lusterIP 地址都不会改变。

,客户端可以通过这个虚拟 IP 地址 服务的端口直接访问该服务,再通过部署 Kubernetes 集群的 DNS 服务,就可以实现 Service Name(域名)到 lusterIP 地址的 DNS 映射功能。我们只要使用服务的名称 DNS 名称 )即可完成到目标服务的访问请求 。
每个 Pod 都有一个特殊的被称为“根容祥"的 Pause 容器 Pause 器对应的镜像属千 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 都还包含一个或多个紧密相关的用户业务容祥。

 

为什么 Kubernetes 会设计出一个全新的 Pod 概念并且 Pod 有这样特殊的组成结构?原如下
  •     为多进程之间的协作提供 个抽象模型,使用 Pod 作为基本的调度 复制等管理工作的最小单位,让多个应用进程能一起有效地调度和伸缩。
  •     Pod 里的 多个业务容器共享 Pause 容器的 IP, 共享 Pause 容器挂接的 Vo lume,样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。
!!!Kubernetes 里, 一个 Pod 里的容器与另外主机上的 Pod 容器能够直接通
Pod分类:
Pod分为普通pod和静态pod,静态pod没有写人etcd,二是在Node上的一个具体文件,并且只能在这个Node上启动。
                                                普通pod一旦创建就会被写入etcd中,随后被Kubernetes Master节点调度到某个Node上并绑定(Banding),该Pod被Node上的kubelet进程实例化成一组Docker容器并启动
                                                默认情况下,当Pod的里边某个容器停止时候,Kubernetes会检测到启动Pod中的所有容器。  
EndPoint:
         Pod的ip加上容器的端口(containerPort),代表此Pod里的一个服务进程对外的通信地址。
         每个​​​Pod​​​都有独有的IP地址,而每次​​​Pod​​​重建后IP地址都会发生变化,那我们如何长期对一个​​​Pod​​​进行访问呢?答案就是​​​Service​​​,​​​Servcie​​​可以理解为一组​​​Pod​​​的四层代理,​​​Service​​​作为​​​kubernets​​​一种标准的资源,它可以通过节点的​​​kube-proxy​​​从​​​apiserver​​​中获取每个​​​Pod​​​的地址,从而实现代理功能。由下图可见,每一个​​​Service​​​资源都有一个​​​endpoints​​​,​​​endpoints​​​主要记录了每个​​​pod​​​的IP地址信息,当​​​Pod​​​的IP发生变化时,endpoints会进行更新。
Endpoints表示一个Service对应的所有Pod副本的访问地址。Node上的Kube-proxy进程获取每个Service的Endpoints,实现Service的负载均衡功能。

 

 

 Endpoints Controller就是负责生成和维护所有Endpoints对象的控制器,它负责监听Service和对应的Pod副本的变化。如果检测到Service被删除,则删除和该Service同名的Endpoints对象。如果检测到新的Service被创建或者修改则根据该Service信息获得相关的Pod列表,然后创建或者更新Service对应的Endpoints对象。

 

Replicaset:
        Kubernetes会根据Deployment对象自动创建相关联的Repliaset对象,通过观察我们发现,Pod的命名也是以replicaset命名为前缀的,
[root@master01 mysql]# kubectl get replicaset
NAME               DESIRED   CURRENT   READY   AGE
mysql-557fd4547d   1         1         1       88m
myweb-c49f967d8    2         2         2       56m
[root@master01 mysql]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
mysql-557fd4547d-m29k6   1/1     Running   0          93m
myweb-c49f967d8-4h7d8    1/1     Running   0          61m
myweb-c49f967d8-6vggh    1/1     Running   0          61m

Pod、Service、Deployment的逻辑关系:

Kubernets的Service定义了一组入口访问地址,前端的应用通过这个地址访问其背后的一组由Pod副本组成的集群实例,Service与后端的Pod的集群是有Label Selector无缝对接的,Deployment是保证Service的服务能力和服务质量,始终符合预期的标准。

 

 

 

 Service的ClusterIP地址
 Kubernetes内部的每个Node上都运行了一套全局的负载均衡器,自动注入,并自动实时更新集群中所有Service的路由表,通过iptables或者IPVS机制,把对Service的请求转发到其后端某个对于的Pod上,并在内部实现服务的负载均衡和会话保持机制。Service一旦被创建,Kubernetes就会给他分配一个全局唯一的ClusterIP,而且在Service的生命周期内,ClusterIP不会发生改变。
服务发现
只要用Service的Name和CluserIP做一个域名映射,比如我们定义一 MySQL Service, Service 的名称是 mydbserver, ervice 的端口是 3306, 则在代码中直接通过mydbserver:3306 即可访问此服务,不再需要任何 API 来获取服务的 IP 地址和端口信息。
Service的事例:
apiVersion: v1
kind: Service
metadata:
  name: testservice
spec:
  clusterIP: 10.96.85.70
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    tier: frontend
  type: ClusterIP
status:
  loadBalancer: {}

各种port的理解

https://www.cnblogs.com/devilwind/p/8881201.html

 

nodePort: 集群外部地址访问集群Service的时候用的端口,比如外部用户要访问k8s集群中的一个Web应用,那么我们可以配置对应service的type=NodePort,nodePort=30001。其他用户就可以通过浏览器http://node:30001访问到该web服务。

port:是暴露在cluster ip上的端口,:port提供了集群内部客户端访问service的入口,即clusterIP:port。 mysql容器暴露了3306端口,集群内其他容器通过33306端口访问mysql服务,但是外部流量不能访问mysql服务,因为mysql服务没有配置NodePort。

targetPort:是pod上的端口,从port/nodePort上来的数据,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。

containerPort:是在pod控制器中定义的、pod中的容器需要暴露的端口。

 总的来说,port和nodePort都是service的端口,前者暴露给k8s集群内部服务访问,后者暴露给k8s集群外部流量访问。从这两个端口到来的数据都需要经过反向代理kube-proxy,流入后端pod的targetPort上,最后到达pod内容器的containerPort

 targetPort:是容器对外暴露的端口,targetport属性用来提供该服务的容器所暴露的(expose)的端口号,即具体的业务进程在容器内的targetport提供TCP/IP接入,port属性定义了Service的端口。
 
Headless  Service
它与普通的Service相比,没有ClusterIP,如果解析Headless Service的域名,则它返回的是该Service对应的全部Pod的Endpoint列表,这意味着客户端直接与后端的PodTCP/IP链接并通信的,没有虚拟的ClusterIP地址进行转发,等同于原生网络通信。
Service的外网访问:
NodePort 的实现方式是,在 Kubernetes 集群的每个 Kode 上都为需要外部访问的Service 开启 一个对应的 监听端口,外部系统只要用任意一个 Node IP 地址+NodePort端口号即可访间此服务.
StatefulSet:
StatefulSet 里的每个 Pod 都有稳定 唯一的网络标识,可以用来发现集群内的其他成员;
StatefulSet 控制的 Pod 副本的启停顺序是受控的;
StatefulSet Pod 采用稳定的持久化存储卷,通过 PV PVC 来实现,删除 Pod默认不会删除与 StatefulSet 相关的存储卷;
Job
Jobs 控制器提供了两个控制并发数的参数: completions表示需要运行任务数的总数,parallelism 表示并发运行的个数,例如parallelism设置为1,则表示任务会依次运行,Job控制的副本数是短暂的,可以将其视为一组容器,其中每个容器都只运行依次。
ConfigMap
 保存配置项的一个Map,用户将配置文件的内容保存到Configmap中,文件名可以作为key,文件内容就是value。

ConfigMap典型用法:

生成容器内的环境变量;

设置容器启动命令的启动参数;

以Volume的形式挂载为容器内部的文件或者目录;

创建一个configMap    testconfig.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-test
data:
  apploglevel: info
  appdatadir:  /var/data

执行kubectl   create   -f     testconfig.yaml 命令创建

第二种方法:直接通过命令   kubectl   create  configmap   testconfig.yaml    --from-file=server.xml

通过 --from-file参数在目录下进行创建,该目录的每个配置文件名都被设置为key,文件的内容被设置为 value 语法如下:

 kubectl create configmap NAME --from-file=config-files-dir

使用 --from-literal 会从文本中进创建, 直接将指定的 key#=value #创建为ConfigMap内容,如下
kubectl create configmap NAME --from-literal=keyl=valuel --from-literal=key2=value2

容器对ConfigMap的用法有以下两种方法:

      (1)通过环境变量获取ConfigMap中的内容;

       (2)通过Volume挂载的方法,将ConfigMap中的内容挂载为容器内部的文件或者目录。

 创建一个ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
data:
  apploglevel: info
  appdatadir: /var/data

[root@master01 configmap]# kubectl create -f conf.yaml

创建pod引用ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: con-test
spec:
  containers:
  - name: mappod
    image: busybox
    command: ["/bin/sh","-c","env|grep APP"]
    env:
    - name: APPLOGLEVEL
      valueFrom:
        configMapKeyRef:
          name: test-config
          key: apploglevel
    - name: APPDATADIR
      valueFrom:
        configMapKeyRef:
          name: test-config
          key: appdatadir
  restartPolicy: Never

[root@master01 configmap]# kubectl create -f pod.yaml 

查看日志:

[root@master01 configmap]# kubectl logs con-test

 

 Secret

保存敏感信息。

HPA

Horizontal Pod Autoscaler  自动实现pod的自动扩容缩容。

Volume

Volume是能够被多个容器访问的共享目录。

emptyDir

一个emptyDri是pod分配到Node上创建的,当Pod从Node上移除时候,目录就会自动删除;用途如下:

临时空间,无需长时间保留;

长时间任务执行过程中使用的临时目录;

一个容器需要从另外一个容器获取数据的目录;

hostPath

在应用容器上生成的日志文件需要长期保存时候,

需要访问Docker内部数据时候

动态存储管理:

Persistetn Volume(PV);

二、Pod

apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: app-logs
      mountPath: /usr/local/tomcat/logs
  - name: buhbux
    image: busybox
    command: ["sh", "-c", "tail -f /logs/catalina*.log"]
    volumeMounts:
    - name: app-logs
      mountPath: /logs  
  volumes:
  - name: app-logs
    emptyDir: {}

 pod的生命周期和重启策略

 

 Pod的重启策略包括Always,OnFailure、Never

Pod的健康检查

    LivenessProbe用户判断容器是否存活(Running),如果LivenessProbe探针判断容器的状态不健康,则kubelet将杀掉该容器,并根据响应的重启策略重启改容器,如果一个容器的探针不包含LivenessProbe,则kubelet则认为该容器的LivenessProbe的返回值永远是Successful。

   ReadinessProbe用户判断容器状态是否为(Ready)达到Ready的状态的Pod才能够接收请求,如果运行状态不是为Ready,自系统自动将其从EndPoint的列表中隔离出去,后续在把恢复到Ready状态的EndPoint加入到列表中,这样保证访问service的时候不会被转发到不可用的Pod上来。

   StartupProbe:某些应用会遇到启动比较慢的情况,可以通过StartupProbe探针解决。

apiVersion: v1
kind: Pod
metadata:
  name: liveness
  labels:
    test: liveness
spec:
  containers:
  - name: livenessdock
    image: busybox
    args:
    - /bin/bash
    - -c
    - echo ok > /tmp/health; sleep 10; rm -rf /tmp/health; sleep 600;
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/health
      initialDelaySeconds: 15
      timeoutSeconds: 1      

 通过检测端口来判断容器的状态

apiVersion: v1
kind: Pod
metadata:
  name: tcp
  labels:
    test: tcp
spec:
  containers:
  - name: liveness 
    image: nginx
    ports:
    - containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds:30
      timeoutSeconds: 1      

HTTPGetAction: 通过容器的 IP地址端口号及路径调用 HTTPGet法,如果响应的状态码大千等于 200 且小于 400, 则认为容器健康。

 
apiVersion: v1
kind: Pod
metadata:
  name: httpget
  labels:
    test: httpget
spec:
  containers:
  - name: httget
    image: nginx
    ports:
    - containerPort: 80
    livenessProbe:
      httpGet:
        path: /_status/healthz
        port: 80
      initialDelaySecond: 30
      timeoutSeconds: 1

initialDelaySeconds: 启动容器后进行首次健康检查的 等待时间,单位为s
timeoutSeconds 健康检查发送请求后等待响应的超时时间,单位为 。当超时发生时, kubele会认为容器已经无法提供服务,将会重启该容器。

 Pod调度
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy01
spec:
  selector:
    matchLabels:
      app: nginxtest
  replicas: 3
  template: 
    metadata: 
      labels:
        app: nginxtest
    spec:
      containers:
      - name: nginxtest
        image: nginx
        ports:
        - containerPort: 80

NodeSelector定向调度

先给node打标签:  

[root@master01 deploy]# kubectl label nodes work01 zone=north

 在Deployment中加入节点的标签

NodeSelector:
   zone: north

NodeAffinity节点亲和性调度:

RequiredDuringSchedulingignoredDuringExecution: 必须满足才可以调度,硬限制;
PreferredDuringSchedulingIgnoredDuringExectuion:强调有限满足指定规则,不强求,相当于软限制;

          IgnoredDuringExecution:表示如果Pod运行中,Labels发生变化,Pod可以继续运行。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
spec:
  
  
apiVersion: v1
kind: Pod
metadata: 
  name: affinity-test
spec:
  containers:
  - name: aff-test
    image: pause
  affinity:
    nodeAffinity
      requiredDruingSchedulingIgnoredDruingExecution:
        nodeSelectorTerms:
        - matchExpressions
          - key: beta.kubernetes.io/arch
            operator: In
            values:
            -amd64
    preferredDuringSchedulingIgnoreDruingExection:
    - weight: 1
      preference:
        matchExpressions:
          - key: disk-type
            operator: In
            values: 
            - ssd

如果 nodeAffinity 指定了多个 nodeSelectorTerms, 那么其中一个能匹配成功即可;

如果在 nodeSelectorTerms 中有多个 matchExpressioos, 则一个节点必须满足所有matchExpressions 才能运行该 Pod

 PodAffinity:
存在某些相互依赖、频繁调用的Pod, 它们需要被尽可能地部署在同 Node 节点;
Taints:
 Taints与NodeAffinity相反,拒绝Pod在Node上运行,给节点标记污点:
kubectl   taint  nodes work1  key=value:NoSchedule
默认情况下,在一个Node上设置一个或者多个Taint以后,除非Pod声明可以容忍这些污点,否则,无法在这些Node上运行,
PreferSchedule :尽量不要调度到这个节点上。
NoExecute:如果pod在这个Node上,则会被驱逐。
给pod设置容忍度,可以调度到刚才有污点的Node上:
tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoSchedule"

Pod  Priority  Preemption :Pod 优先级调度

DaemonSet:
每个Node上都调度一个Pod
 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-cloud-logging
  namespace: kube-system
  labels:
    k8s-app: fluentd-cloud-logging
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-cloud-logging
  template:
    metadata:
      namespace: kube-system
      labels:
        k8s-app: fluentd-cloud-logging
    spec:
      containers:
      - name: fluentd-cloud-logging
        image: gcr.io/google_containers/fluentd-elasticsearch:1.17
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
        env:
        - name: FLUENTD_ARGS
          value: -q
        volumeMounts:
        - name: varlog
          mountPath: /var/log
          readOnly: false
        - name: containers
          mountPath: /var/lib/docker/containers
          readOnly: false
      volumes:
      - name: containers
        hostPath:
          path: /var/lib/docker/containers
      - name: varlog
        hostPath:
          path: /var/log

 CronJob:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

Init Container初始化容器

 init  Container与应用容器在本质上是一致的,但他们是仅仅运行一次就结束的任务,并且必须在运行成功后,系统才能执行下一个容器,根据Pod的重启策略(RestartPolicy),当init container运行失败而且设置了RestartPolicy=Never时候,Pod将启动失败,而设置RestartPolicy=Always时候,Pod将会被系统自动启动。

 

apiVersion: v1
kind: Pod
metadata:
  name: ngi
  namespace: default
spec:
  initContainers:
  - name: install
    image: busybox
    command:
    - wget
    - "-O"
    - "/work-dir/index.html"
    - http://kubernetes.io
    volumeMounts:
    - name: workdir
      mountPath: "/work-dir"
  containers:
  - name: nginx
    image: nginx
    ports: 
     - containerPort: 80
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  dnsPolicy: Default
  volumes:
  - name: workdir
    emptyDir: {}

[root@master01 initCont]# kubectl get pod -owide

[root@master01 initCont]# curl https://10.244.75.124:80/index.html

 
 
 
 
 
 
posted @ 2023-04-07 09:54  中仕  阅读(202)  评论(0编辑  收藏  举报