k8s入门篇-资源管理

Kubernetes入门

一、为什么需要Kubernetes

1.1 传统的容器编排痛点

容器技术虽然解决了应用和基础设施异构的问题,让应用可以做到一次构建,多次部署,但在复杂的微服务场景,单靠 Docker 技术还不够,它仍然有以下问题没有解决:

  • 集成和编排微服务模块
  • 提供按需自动扩容,缩容能力
  • 故障自愈
  • 集群内的通信

 

1.2 Kubernetes 能解决的问题

  • 按需的垂直扩容,新的服务器(node)能够轻易的增加或删除
  • 按需的水平扩容,容器实例能够轻松扩容,缩容
  • 副本控制器,你不用担心副本的状态
  • 服务发现和路由
  • 自动部署和回滚,如果应用状态错误,可以实现自动回滚

 

1.3 什么时候使用 Kubernetes?

  • 应用是微服务架构
  • 开发者需要快速部署自己的新功能到测试环境进行验证
  • 降低硬件资源成本,提高使用率

 

1.4 什么时候不适合使用 Kubernetes

  • 应用是轻量级的单体应用,没有高并发的需求
  • 团队文化不适应变革

二、Kubernetes的发展

  • 2014年6月 谷歌云计算专家Eric Brewer在旧金山的发布会为这款新的开源工具揭牌。
  • 2015年7月22日K8S迭代到 v 1.0并在OSCON大会上正式对外公布。为了建立容器编排领域的标准和规范,Google、RedHat 等开源基础设施领域玩家们,在 2015 年共同牵头发起了名为 CNCF(Cloud Native Computing Foundation)的基金会。Kubernetes 成为 CNCF 最核心的项目。

   发起成员:AT&T, Box, Cisco, Cloud Foundry Foundation, CoreOS, Cycle Computing, Docker, eBay, Goldman Sachs, Google, Huawei, IBM, Intel, Joyent, Kismatic, Mesosphere, Red Hat, Switch SUPERNAP, Twitter, Univa, VMware and Weaveworks。

  • 2018年,超过 1700 开发者成为 Kubernetes 项目社区贡献者,全球有 500 多场沙龙。国内出现大量基于 Kubernetes 的创业公司。
  • 2020 年,Kubernetes 项目已经成为贡献者仅次于 Linux 项目的第二大开源项目。成为了业界容器编排的事实标准,各大厂商纷纷宣布支持 Kubernetes 作为容器编排的方案。

三、kubernetes组成

3.1 Master节点

  • Kube-APIServer:集群的控制中枢,各个模块之间信息交互都需要经过Kube-APIServer,同时它也是集群管理、资源配额、整个集群安全机制的入口。【信息交互,大脑】
  • Controller-Manager:集群的状态管理器,保证Pod或其他资源达到期望值,也是需要和APIServer进行通信,在需要的时候创建、更新或删除它所管理的资源。【资源管理,控制】
  • Scheduler:集群的调度中心,它会根据指定的一系列条件,选择一个或一批最佳的节点,然后部署我们的Pod。【资源分配,调度】
  • Etcd:键值数据库,保存一些集群的信息,一般生产环境中建议部署三个以上节点(奇数个)。【数据存储,存储】

3.2 Node工作节点

   Worker、node节点、minion节点

  • Kubelet:负责监听节点上Pod的状态,同时负责上报节点和节点上面Pod的状态,负责与Master节点通信,并管理节点上面的Pod。
  • Kube-proxy:负责Pod之间的通信和负载均衡,将指定的流量分发到后端正确的机器上。

    查看Kube-proxy工作模式:curl 127.0.0.1:10249/proxyMode

     Ipvs:监听Master节点增加和删除service以及endpoint的消息,调用Netlink接口创建相应的IPVS规则。通过IPVS规则,将流量转发至相应的Pod上。

     Iptables:监听Master节点增加和删除service以及endpoint的消息,对于每一个Service,他都会创建一个iptables规则,将service的clusterIP代理到后端对应的Pod。

3.3 其他组件

  • Calico:符合CNI标准的网络插件,给每个Pod生成一个唯一的IP地址,并且把每个节点当做一个路由器。最新Cilium插件,可关注
  • CoreDNS:用于Kubernetes集群内部Service的解析,可以让Pod把Service名称解析成IP地址,然后通过Service的IP地址进行连接到对应的应用上。
  • Docker:容器引擎,负责对容器的管理。

 

四、Pod

4.1 Pod是什么

Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成,每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过Pause容器可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。

4.2 Pod定义

apiVersion: v1 # 必选,API的版本号
kind: Pod       # 必选,类型Pod
metadata:       # 必选,元数据
  name: nginx   # 必选,符合RFC 1035规范的Pod名称
  namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace 
  labels:       # 可选,标签选择器,一般用于过滤和区分Pod
    app: nginx
    role: frontend # 可以写多个
  annotations:  # 可选,注释列表,可以写多个
    app: nginx  #格式要求不是很严格
spec:   # 必选,用于定义容器的详细信息
  initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作
  - command:
    - sh
    - -c
    - echo "I am InitContainer for init some configuration"
    image: busybox
    imagePullPolicy: IfNotPresent
    name: init-container
  containers:   # 必选,容器列表
  - name: nginx # 必选,符合RFC 1035规范的容器名称
    image: nginx:latest    # 必选,容器所用的镜像的地址
    imagePullPolicy: Always     # 可选,镜像拉取策略
    command: # 可选,容器启动执行的命令
    - nginx 
    - -g
    - "daemon off;"
    workingDir: /usr/share/nginx/html       # 可选,容器的工作目录
    volumeMounts:   # 可选,存储卷配置,可以配置多个
    - name: webroot # 存储卷名称
      mountPath: /usr/share/nginx/html # 挂载目录
      readOnly: true        # 只读
    ports:  # 可选,容器需要暴露的端口号列表
    - name: http    # 端口名称
      containerPort: 80     # 端口号
      protocol: TCP # 端口协议,默认TCP
    env:    # 可选,环境变量配置列表
    - name: TZ      # 变量名
      value: Asia/Shanghai # 变量的值
    - name: LANG
      value: en_US.utf8
    resources:      # 可选,资源限制和资源请求限制
      limits:       # 最大限制设置
        cpu: 1000m
        memory: 1024Mi
      requests:     # 启动所需的资源
        cpu: 100m
        memory: 512Mi
#    startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
#      httpGet:      # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
#            path: /api/successStart # 检查路径
#            port: 80
    readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
      httpGet:      # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
            path: / # 检查路径
            port: 80        # 监控端口
    livenessProbe:  # 可选,健康检查
      #exec:        # 执行容器命令检测方式
            #command: 
            #- cat
            #- /health
    #httpGet:       # httpGet检测方式
    #   path: /_health # 检查路径
    #   port: 8080
    #   httpHeaders: # 检查的请求头
    #   - name: end-user
    #     value: Jason 
      tcpSocket:    # 端口检测方式
            port: 80
      initialDelaySeconds: 60       # 初始化时间
      timeoutSeconds: 2     # 超时时间
      periodSeconds: 5      # 检测间隔
      successThreshold: 1 # 检查成功为2次表示就绪
      failureThreshold: 2 # 检测失败1次表示未就绪
    lifecycle:
      postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket
        exec:
          command:
          - sh
          - -c
          - 'mkdir /data/ '
      preStop:
        httpGet:      
              path: /
              port: 80
      #  exec:
      #    command:
      #    - sh
      #    - -c
      #    - sleep 9
  restartPolicy: Always   # 可选,默认为Always
  #nodeSelector: # 可选,指定Node节点
  #      region: subnet7
  imagePullSecrets:     # 可选,拉取镜像使用的secret,可以配置多个
  - name: default-dockercfg-86258
  hostNetwork: false    # 可选,是否为主机模式,如是,会占用主机端口
  volumes:      # 共享存储卷列表
  - name: webroot # 名称,与上述对应
    emptyDir: {}    # 挂载目录
        #hostPath:              # 挂载本机目录
        #  path: /etc/hosts

 

 

4.3  零宕机必备之Pod探针

  • StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。如果配置了startupProbe,就会先禁止其他的探测,直到它成功为止,成功后将不在进行探测。【判断容器内的程序是否正常提供服务】
  • LivenessProbe:用于探测容器是否运行,如果探测失败,kubelet会根据配置的重启策略进行相应的处理。若没有配置该探针,默认就是success。【判断容器是否运行或者判断容器是否需要重启】
  • ReadinessProbe:一般用于探测容器内的程序是否健康,它的返回值如果为success,那么久代表这个容器已经完成启动,并且程序已经是可以接受流量的状态。【判断容器内的程序是否健康】

 

4.3.1 Pod探针的检测方式

  • ExecAction:在容器内执行一个命令,如果返回值为0,则认为容器健康。
  • TCPSocketAction:通过TCP连接检查容器内的端口是否是通的,如果是通的就认为容器健康。
  • HTTPGetAction:通过应用程序暴露的API地址来检查程序是否是正常的,如果状态码为200~400之间,则认为容器健康。

 

4.3.2 探针使用场景

  • LivenessProbe探针

         如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针; kubelet 将根据 Pod 的 restartPolicy 自动执行修复操作。

        如果你希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针, 并指定 restartPolicy 为 "Always" 或 "OnFailure"。

 

  • ReadinessProbe探针

         如果要仅在探测成功时才开始向 Pod 发送请求流量,请指定就绪态探针。 在这种情况下,就绪态探针可能与存活态探针相同,但是规约中的就绪态探针的存在意味着 Pod 将在启动阶段不接收任何数据,并且只有在探针探测成功后才开始接收数据。

         如果你希望容器能够自行进入维护状态,也可以指定一个就绪态探针, 检查某个特定于就绪态的因此不同于存活态探测的端点。

        如果你的应用程序对后端服务有严格的依赖性,你可以同时实现存活态和就绪态探针。 当应用程序本身是健康的,存活态探针检测通过后,就绪态探针会额外检查每个所需的后端服务是否可用。 这可以帮助你避免将流量导向只能返回错误信息的 Pod。

        如果你的容器需要在启动期间加载大型数据、配置文件或执行迁移, 你可以使用启动探针。 然而,如果你想区分已经失败的应用和仍在处理其启动数据的应用,你可能更倾向于使用就绪探针。

 

  • StartupProbe探针

   对于所包含的容器需要较长时间才能启动就绪的 Pod 而言,启动探针是有用的。 你不再需要配置一个较长的存活态探测时间间隔,只需要设置另一个独立的配置选定, 对启动期间的容器执行探测,从而允许使用远远超出存活态时间间隔所允许的时长。

  如果你的容器启动时间通常超出 initialDelaySeconds + failureThreshold × periodSeconds 总值,你应该设置一个启动探测,对存活态探针所使用的同一端点执行检查。 periodSeconds 的默认值是 10 秒。你应该将其 failureThreshold 设置得足够高, 以

  便容器有充足的时间完成启动,并且避免更改存活态探针所使用的默认值。 这一设置有助于减少死锁状况的发生。

 

 4.3.3 探针参数

#      initialDelaySeconds: 60       # 初始化时间,容器初始化的时间

#      timeoutSeconds: 2     # 超时时间

#      periodSeconds: 5      # 检测间隔

#      successThreshold: 1 # 检查成功为1次表示就绪

#      failureThreshold: 2 # 检测失败2次表示未就绪

 

探针整体设计思路:

由于有些程序可能启动时间比较长,所以新增了StartupProbe探针。一旦启用了StartupProbe探针,其他2个就禁用了,等StartupProbe探针检测完成后,再进行容器存活和容器ready检测。

 

4.4 pod的退出流程

pod退出的流程,当用户执行删除pod操作时:

1、pod的状态变为terminating

2、endpoint中删除该pod的ip

3、执行prestop命令,进行pod退出前的一些清理操作

优雅退出默认时间:30s

terminationGracePeriodSeconds: 30

如果我们希望更长,可以进行配置;或者命令行  kubectl delete pod nginx --grace-period=40

 

4.5 pod实践

定义一个pod

apiVersion: v1 # 必选,API的版本号
kind: Pod       # 必选,类型Pod
metadata:       # 必选,元数据
  name: nginx   # 必选,符合RFC 1035规范的Pod名称
  namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace 
  labels:       # 可选,标签选择器,一般用于过滤和区分Pod
    app: nginx
    role: frontend # 可以写多个
  annotations:  # 可选,注释列表,可以写多个
    app: nginx
spec:   # 必选,用于定义容器的详细信息
  containers:   # 必选,容器列表
  - name: nginx # 必选,符合RFC 1035规范的容器名称
    image: nginx:1.15.2    # 必选,容器所用的镜像的地址
    imagePullPolicy: IfNotPresent     # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
    command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
    - nginx 
    - -g
    - "daemon off;"
    workingDir: /usr/share/nginx/html       # 可选,容器的工作目录
    ports:  # 可选,容器需要暴露的端口号列表
    - name: http    # 端口名称
      containerPort: 80     # 端口号
      protocol: TCP # 端口协议,默认TCP
    env:    # 可选,环境变量配置列表
    - name: TZ      # 变量名
      value: Asia/Shanghai # 变量的值
    - name: LANG
      value: en_US.utf8
      #exec:        # 执行容器命令检测方式
            #command: 
            #- cat
            #- /health
    startupProbe:
      tcpSocket:
        port: 80

 创建pod

[root@k8s-master01 ~]# kubectl apply -f nginx-pod.yaml 
pod/nginx created

 查看pod

[root@k8s-master01 ~]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          32s

  

查看pod实时动态

kubectl get pod -w
kubectl

  

五、RC和RS

Replication Controller(复制控制器,RC)和ReplicaSet(复制集,RS)是两种简单部署Pod的方式。因为在生产环境中,主要使用更高级的Deployment等方式进行Pod的管理和部署,所以本节只对Replication Controller和Replica Set的部署方式进行简单介绍。

5.1 Replication Controller

Replication Controller(简称RC)可确保Pod副本数达到期望值,也就是RC定义的数量。换句话说,Replication Controller可确保一个Pod或一组同类Pod总是可用。

如果存在的Pod大于设定的值,则Replication Controller将终止额外的Pod。如果太小,Replication Controller将启动更多的Pod用于保证达到期望值。与手动创建Pod不同的是,用Replication Controller维护的Pod在失败、删除或终止时会自动替换。因此即使应用程序只需要一个Pod,也应该使用Replication Controller或其他方式管理。Replication Controller类似于进程管理程序,但是Replication Controller不是监视单个节点上的各个进程,而是监视多个节点上的多个Pod。

定义一个Replication Controller的示例如下。

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

  

5.2 ReplicaSet

ReplicaSet是支持基于集合的标签选择器的下一代Replication Controller,它主要用作Deployment协调创建、删除和更新Pod,和Replication Controller唯一的区别是,ReplicaSet支持标签选择器。在实际应用中,虽然ReplicaSet可以单独使用,但是一般建议使用Deployment来自动管理ReplicaSet,除非自定义的Pod不需要更新或有其他编排等。

定义一个ReplicaSet的示例如下:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # modify replicas according to your case
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
      - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access environment variables to find service host
          # info, comment out the 'value: dns' line above, and uncomment the
          # line below.
          # value: env
        ports:
        - containerPort: 80

  Replication Controller和ReplicaSet的创建删除和Pod并无太大区别,Replication Controller目前几乎已经不在生产环境中使用,ReplicaSet也很少单独被使用,都是使用更高级的资源Deployment、DaemonSet、StatefulSet进行管理Pod。

 

六、Deployment

用于部署无状态的服务,这个最常用的控制器。一般用于管理维护企业内部无状态的微服务,比如configserver、zuul、springboot。他可以管理多个副本的Pod实现无缝迁移、自动扩容缩容、自动灾难恢复、一键回滚等功能。

 

6.1 创建一个Deployment

手动创建:

kubectl create deployment nginx --image=nginx:1.15.2

  

从文件创建:

# cat nginx-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2020-09-19T02:41:11Z"
  generation: 1
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 2 #副本数
  revisionHistoryLimit: 10 # 历史记录保留的个数
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

 
从文件创建:

kubelet apply -f nginx-deploy.yaml

  

查看deployment

[root@k8s-master01 ~/k8s]# kubectl get deploy -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES         SELECTOR
nginx   2/2     2            2           3m42s   nginx        nginx:1.15.2   app=nginx
  • NAME: Deployment名称
  • READY:Pod的状态,已经Ready的个数
  • UP-TO-DATE:已经达到期望状态的被更新的副本数
  • AVAILABLE:已经可以用的副本数
  • AGE:显示应用程序运行的时间
  • CONTAINERS:容器名称
  • IMAGES:容器的镜像
  • SELECTOR:管理的Pod的标签

  

可以直接通过修改replicas数量来动态调整pod的数量,pod创建后,不可动态修改labels,需要删掉pod后,重建pod才行。

 

6.2 Deployment的更新

更改deployment的镜像并记录:

kubectl set image deploy nginx nginx=nginx:1.15.3 –record

  

查看更新过程:

# kubectl rollout status deploy nginx
deployment "nginx" successfully rolled out
[root@k8s-master01 ~]# kubectl rollout status deploy nginx
Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
deployment "nginx" successfully rolled out

  

或者使用describe查看:

# kubectl describe deploy nginx  
Normal  ScalingReplicaSet  25m                  deployment-controller  Scaled up replica set nginx-66bbc9fdc5 to 1
  Normal  ScalingReplicaSet  18m (x2 over 23m)    deployment-controller  Scaled up replica set nginx-66bbc9fdc5 to 2
  Normal  ScalingReplicaSet  7m7s                 deployment-controller  Scaled up replica set nginx-5dfc8689c6 to 1
  Normal  ScalingReplicaSet  6m28s (x2 over 23m)  deployment-controller  Scaled down replica set nginx-66bbc9fdc5 to 1
  Normal  ScalingReplicaSet  6m27s                deployment-controller  Scaled up replica set nginx-5dfc8689c6 to 2
  Normal  ScalingReplicaSet  5m58s                deployment-controller  Scaled down replica set nginx-66bbc9fdc5 to 0
  Normal  ScalingReplicaSet  4m19s                deployment-controller  Scaled up replica set nginx-6cdd5dd489 to 1
  Normal  ScalingReplicaSet  3m44s                deployment-controller  Scaled down replica set nginx-5dfc8689c6 to 1
  Normal  ScalingReplicaSet  3m44s                deployment-controller  Scaled up replica set nginx-6cdd5dd489 to 2
  Normal  ScalingReplicaSet  3m6s                 deployment-controller  Scaled down replica set nginx-5dfc8689c6 to 0

  

 

6.3  Deployment的回滚

# 执行更新操作

模拟操作一个不存在或者错误的镜像:

[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977da --record
deployment.apps/nginx image updated
[root@k8s-master01 ~]# kubectl get po 
NAME                     READY   STATUS              RESTARTS   AGE
nginx-6cdd5dd489-lv28z   1/1     Running             0          7m12s
nginx-6cdd5dd489-nqqz7   1/1     Running             0          6m37s
nginx-7d79b96f68-x7t67   0/1     ContainerCreating   0          19s

  

查看历史版本

[root@k8s-master01 ~]# kubectl rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deploy nginx nginx=nginx:1.15.3 --record=true
3         kubectl set image deploy nginx nginx=nginx:1.15.4 --record=true
4         kubectl set image deploy nginx nginx=nginx:787977da --record=true

  

回滚到上一个版本

[root@k8s-master01 ~]# kubectl rollout undo deploy nginx 
deployment.apps/nginx rolled back

  

查看回滚结果

[root@k8s-master01 ~]# kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6cdd5dd489-lv28z   1/1     Running   0          9m8s
nginx-6cdd5dd489-nqqz7   1/1     Running   0          8m33s
[root@k8s-master01 ~]# kubectl get deploy nginx -oyaml | grep nginx
    kubernetes.io/change-cause: kubectl set image deploy nginx nginx=nginx:1.15.4
    app: nginx
              k:{"name":"nginx"}:
              k:{"name":"nginx"}:
  name: nginx
  selfLink: /apis/apps/v1/namespaces/default/deployments/nginx
      app: nginx
        app: nginx
      - image: nginx:1.15.4
        name: nginx
    message: ReplicaSet "nginx-6cdd5dd489" has successfully progressed.

  

进行多次更新

[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977da --record
deployment.apps/nginx image updated
[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977dadaa --record
deployment.apps/nginx image updated
[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977xxxxxdadaa --record
deployment.apps/nginx image updated
[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977dadxxxxxdadaa --record
deployment.apps/nginx image updated
[root@k8s-master01 ~]# # 查看历史记录
[root@k8s-master01 ~]# kubectl  rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deploy nginx nginx=nginx:1.15.3 --record=true
5         kubectl set image deploy nginx nginx=nginx:1.15.4 --record=true
6         kubectl set image deploy nginx nginx=nginx:787977da --record=true
7         kubectl set image deploy nginx nginx=nginx:787977dadaa --record=true
8         kubectl set image deploy nginx nginx=nginx:787977xxxxxdadaa --record=true
9         kubectl set image deploy nginx nginx=nginx:787977dadxxxxxdadaa --record=true

  

查看指定版本的详细信息

[root@k8s-master01 ~]# kubectl rollout history deploy nginx --revision=5
deployment.apps/nginx with revision #5
Pod Template:
  Labels:	app=nginx
	pod-template-hash=6cdd5dd489
  Annotations:	kubernetes.io/change-cause: kubectl set image deploy nginx nginx=nginx:1.15.4 --record=true
  Containers:
   nginx:
    Image:	nginx:1.15.4
    Port:	<none>
    Host Port:	<none>
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>

  

回滚到任意指定版本

[root@k8s-master01 ~]# kubectl rollout undo deploy nginx --to-revision=5
deployment.apps/nginx rolled back

  

查看deploy状态

[root@k8s-master01 ~]# kubectl get deploy -oyaml

  

 

6.4  Deployment的暂停

Deployment 暂停功能

[root@k8s-master01 ~]# kubectl rollout pause deployment nginx 
deployment.apps/nginx paused

  

暂停后多次配置

第一次配置

修改deploy镜像

[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:1.15.3 --record
deployment.apps/nginx image updated

 

第二次配置  

暂停后添加内存CPU配置

[root@k8s-master01 ~]# kubectl set resources deploy nginx -c nginx --limits=cpu=200m,memory=128Mi --requests=cpu=10m,memory=16Mi
deployment.apps/nginx resource requirements updated
[root@k8s-master01 ~]# kubectl get deploy nginx -oyaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "11"
    kubernetes.io/change-cause: kubectl set image deploy nginx nginx=nginx:1.15.3
      --record=true
  creationTimestamp: "2020-09-19T02:41:11Z"
  generation: 18
  labels:
    app: nginx
  name: nginx
  namespace: default
  resourceVersion: "2660534"
  selfLink: /apis/apps/v1/namespaces/default/deployments/nginx
  uid: 1d9253a5-a36c-48cc-aefe-56f95967db66
spec:
  paused: true
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.15.3
        imagePullPolicy: IfNotPresent
        name: nginx
        resources:
          limits:
            cpu: 200m
            memory: 128Mi
          requests:
            cpu: 10m
            memory: 16Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 2
  conditions:
  - lastTransitionTime: "2020-09-19T03:26:50Z"
    lastUpdateTime: "2020-09-19T03:26:50Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: "2020-09-19T03:30:15Z"
    lastUpdateTime: "2020-09-19T03:30:15Z"
    message: Deployment is paused
    reason: DeploymentPaused
    status: Unknown
    type: Progressing
  observedGeneration: 18
  readyReplicas: 2
  replicas: 2

  

查看pod是否被更新

[root@k8s-master01 ~]# kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6cdd5dd489-lv28z   1/1     Running   0          30m
nginx-6cdd5dd489-nqqz7   1/1     Running   0          30m

  

6.5  Deployment的恢复

[root@k8s-master01 ~]# kubectl rollout resume deploy nginx 
deployment.apps/nginx resumed
[root@k8s-master01 ~]# kubectl get rs
NAME               DESIRED   CURRENT   READY   AGE
nginx-5475c49ffb   0         0         0       21m
nginx-5dfc8689c6   0         0         0       33m
nginx-66bbc9fdc5   0         0         0       52m
nginx-68db656dd8   1         1         0       15s
nginx-6cdd5dd489   2         2         2       31m
nginx-799b8478d4   0         0         0       21m
nginx-7d79b96f68   0         0         0       24m
nginx-f974656f7    0         0         0       21m

  

 

6.6  Deployment的扩缩容

kubectl scale --replicas=1 deploy nginx

  扩缩容不会增加rs,因为他只是增加或减少某个rs下的pod数量。

 

 

6.7  Deployment的配置项

  • .spec.revisionHistoryLimit:设置保留RS旧的revision的个数,设置为0的话,不保留历史数据
  • .spec.minReadySeconds:可选参数,指定新创建的Pod在没有任何容器崩溃的情况下视为Ready最小的秒数,默认为0,即一旦被创建就视为可用。

滚动更新的策略:

.spec.strategy.type:更新deployment的方式,默认是RollingUpdate

  • RollingUpdate:滚动更新,可以指定maxSurge和maxUnavailable

     maxUnavailable:指定在回滚或更新时最大不可用的Pod的数量,可选字段,默认25%,可以设置成数字或百分比,如果该值为0,那么maxSurge就不能0。

    maxSurge:可以超过期望值的最大Pod数,可选字段,默认为25%,可以设置成数字或百分比,如果该值为0,那么maxUnavailable不能为0

    假如副本4个,如果最大不可用设置成0,最大期望也是0,那就没法滚动了。最大不可用至少为1,最大期望值可以是0或者以上的值,才能进行滚动;

    同理,最大期望如果设置成0,则最大不可用至少必须设置1,才能进行滚动。

  •  Recreate:重建,先删除旧的Pod,再创建新的Pod

 

七、StatefulSet

StatefulSet(有状态集,缩写为sts)常用于部署有状态的且需要有序启动的应用程序,比如在进行SpringCloud项目容器化时,Eureka的部署是比较适合用StatefulSet部署方式的,可以给每个Eureka实例创建一个唯一且固定的标识符,并且每个Eureka实例无需配置多余的Service,其余Spring Boot应用可以直接通过Eureka的Headless Service即可进行注册。

Eureka的statefulset的资源名称是eureka,eureka-0 eureka-1 eureka-2

Service:headless service,没有ClusterIP eureka-svc

Eureka-0.eureka-svc.NAMESPACE_NAME  
eureka-1.eureka-svc.NAMESPACE_NAME
eureka-N-1.eureka-svc......

  

  

7.1  StatefulSet的基本概念

StatefulSet主要用于管理有状态应用程序的工作负载API对象。比如在生产环境中,可以部署ElasticSearch集群、MongoDB集群或者需要持久化的RabbitMQ集群、Redis集群、Kafka集群和ZooKeeper集群等。

和Deployment类似,一个StatefulSet也同样管理着基于相同容器规范的Pod。不同的是,StatefulSet为每个Pod维护了一个粘性标识。这些Pod是根据相同的规范创建的,但是不可互换,每个Pod都有一个持久的标识符,在重新调度时也会保留,一般格式为StatefulSetName-Number。比如定义一个名字是Redis-Sentinel的StatefulSet,指定创建三个Pod,那么创建出来的Pod名字就为Redis-Sentinel-0、Redis-Sentinel-1、Redis-Sentinel-2。而StatefulSet创建的Pod一般使用Headless Service(无头服务)进行通信,和普通的Service的区别在于Headless Service没有ClusterIP,它使用的是Endpoint进行互相通信,Headless一般的格式为:

statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local。

说明:

  • serviceName为Headless Service的名字,创建StatefulSet时,必须指定Headless Service名称;
  • 0..N-1为Pod所在的序号,从0开始到N-1;
  • statefulSetName为StatefulSet的名字;
  • namespace为服务所在的命名空间;
  • .cluster.local为Cluster Domain(集群域)。

假如公司某个项目需要在Kubernetes中部署一个主从模式的Redis,此时使用StatefulSet部署就极为合适,因为StatefulSet启动时,只有当前一个容器完全启动时,后一个容器才会被调度,并且每个容器的标识符是固定的,那么就可以通过标识符来断定当前Pod的角色。

比如用一个名为redis-ms的StatefulSet部署主从架构的Redis,第一个容器启动时,它的标识符为redis-ms-0,并且Pod内主机名也为redis-ms-0,此时就可以根据主机名来判断,当主机名为redis-ms-0的容器作为Redis的主节点,其余从节点,那么Slave连接Master主机配置就可以使用不会更改的Master的Headless Service,此时Redis从节点(Slave)配置文件如下:

port 6379

slaveof redis-ms-0.redis-ms.public-service.svc.cluster.local 6379

tcp-backlog 511

timeout 0

tcp-keepalive 0

……

  

其中redis-ms-0.redis-ms.public-service.svc.cluster.local是Redis Master的Headless Service,在同一命名空间下只需要写redis-ms-0.redis-ms即可,后面的public-service.svc.cluster.local可以省略

7.2   StatefulSet注意事项

一般StatefulSet用于有以下一个或者多个需求的应用程序:

  • 需要稳定的独一无二的网络标识符。
  • 需要持久化数据。
  • 需要有序的、优雅的部署和扩展。
  • 需要有序的自动滚动更新。

StatefulSet注意事项

  • 如果应用程序不需要任何稳定的标识符或者有序的部署、删除或者扩展,应该使用无状态的控制器部署应用程序,比如Deployment或者ReplicaSet。
  • StatefulSet是Kubernetes 1.9版本之前的beta资源,在1.5版本之前的任何Kubernetes版本都没有。
  • Pod所用的存储必须由PersistentVolume Provisioner(持久化卷配置器)根据请求配置StorageClass,或者由管理员预先配置,当然也可以不配置存储。
  • 为了确保数据安全,删除和缩放StatefulSet不会删除与StatefulSet关联的卷,可以手动选择性地删除PVC和PV(关于PV和PVC请参考2.2.12节)。
  • StatefulSet目前使用Headless Service(无头服务)负责Pod的网络身份和通信,需要提前创建此服务。
  • 删除一个StatefulSet时,不保证对Pod的终止,要在StatefulSet中实现Pod的有序和正常终止,可以在删除之前将StatefulSet的副本缩减为0。

 

7.3 创建一个StatefulSet

[root@k8s-master01 ~/k8s]# cat nginx-sts.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.2
        ports:
        - containerPort: 80
          name: web

  

创建statefulset

[root@k8s-master01 ~/k8s]# kubectl apply -f nginx-sts.yaml 
service/nginx created
statefulset.apps/web created

  

查看statefulset的svc

web-1                    1/1     Running   0          10s
[root@k8s-master01 ~/k8s]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   192.168.0.1   <none>        443/TCP   21d
nginx        ClusterIP   None          <none>        80/TCP    18s

  新创建的statefulset的svc是一个无头服务,也就是他没有ep,直接可以通过svc进行访问服务,这样就少了一层代理。

我们直接通过服务访问后端pod,启动一个busybox:

cat<<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
EOF

  

对服务进程访问

[root@k8s-master01 ~/k8s]# kubectl get pods -owide
NAME                     READY   STATUS    RESTARTS   AGE     IP               NODE           NOMINATED NODE   READINESS GATES
busybox                  1/1     Running   0          38s     172.17.125.14    k8s-node01     <none>           <none>
nginx                    1/1     Running   0          120m    172.25.244.200   k8s-master01   <none>           <none>
nginx-5dfc8689c6-bdxk7   1/1     Running   0          65m     172.27.14.195    k8s-node02     <none>           <none>
web-0                    1/1     Running   0          3m53s   172.25.92.71     k8s-master02   <none>           <none>
web-1                    1/1     Running   0          3m52s   172.17.125.13    k8s-node01     <none>           <none>
[root@k8s-master01 ~/k8s]# kubectl exec -it busybox sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ping web-0.nginx.default
PING web-0.nginx.default (172.25.92.71): 56 data bytes
64 bytes from 172.25.92.71: seq=0 ttl=62 time=0.244 ms

  可以看到,我们通过statefulset-name-0.svc-name.namespace.svc.cluster.local进行服务访问。

 

7.4 statefulset特征

1、启动的时候,一定是web-0启动成功后,才会启动web-1;同样,删除的时候,是从最后一个开始删,删除最后一个后,再删除倒数第二个。

 

 

7.5 statfulset更新

apiVersion: apps/v1
kind: StatefulSet
metadata:
  annotations:
  name: web
  namespace: default
spec:
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  serviceName: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          name: web
          protocol: TCP
        resources: 
          limits:
            cpu: 1000m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 10Mi
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
  updateStrategy:
    rollingUpdate:
      partition: 0
    type: RollingUpdate

  更新策略:滚动更新

 

7.6 statfulset灰度发布

 partition参数设置
apiVersion: apps/v1
kind: StatefulSet
metadata:
  annotations:
  name: web
  namespace: default
spec:
  replicas: 5
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  serviceName: nginx
  template:
    metadata:
      labels:
        app: nginx
        type: statefulset
    spec:
      containers:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          name: web
          protocol: TCP
        resources: 
          limits:
            cpu: 1000m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 10Mi
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
  updateStrategy:
    rollingUpdate:
      partition: 3  # 从第三个pod开始更新
    type: RollingUpdate

  

 

7.7 statfulset删除和级联删除

 级联删除:删除statefulset的同时删除pod(默认)

kubectl delete sts web

  

非级联删除:删除statefulset的同时不删除pod

kubectl delete sts web --cascade=false

  这样删除会出现孤儿pod,即pod无法管理了,删除pod后就没了。

 

7.8 statfulset更新和回滚

statefulset更新:

kubectl set image sts web nginx=nginx:1.15.1 --record=true

  

 

statefulset回滚:

#查看历史版本
kubectl rollout history sts web
#回滚到上一个版本
kubectl rollout undo sts web

  

 

 

 statefulset回滚到任意指定版本:

#查看历史版本
kubectl rollout history sts web

#查看当前镜像
kubectl get pods -l type=statefulset -o yaml|grep image

#回滚到指定版本
kubectl rollout undo sts web --to-revision=14

#查看当前镜像
kubectl get pods -l type=statefulset -o yaml|grep image

  

 

 

 

九、DaemoSet

 

9.1 DaemonSet是什么?

DaemonSet:守护进程集,缩写为ds,在所有节点或者是匹配的节点上都部署一个Pod。

使用DaemonSet的场景

  • 运行集群存储的daemon,比如ceph或者glusterd
  • 节点的CNI网络插件,calico
  • 节点日志的收集:fluentd或者是filebeat
  • 节点的监控:node exporter
  • 服务暴露:部署一个ingress nginx

 

9.2 定义一个DaemonSet

apiVersion: apps/v1
kind: DaemonSet
metadata:
  annotations:
  name: web
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        ds: "true" 
      containers:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          name: web
          protocol: TCP
        resources: 
          limits:
            cpu: 1000m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 10Mi
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

  其中:nodeSelector用于节点选择。

kubectl label node k8s-node01 ds=true

  

节点打上标签后就会在上面创建对应的pod。

 

 

 

9.3 DaemonSet更新和回滚

 Daemonset更新

 

 

  Daemonset回滚

 

 

9.4 DaemonSet更新策略

#滚动更新 
updateStrategy:
      rollingUpdate:
        maxSurge: 0
        maxUnavailable: 1
      type: RollingUpdate 


#即使删除
 updateStrategy:
      rollingUpdate:
        maxSurge: 0
        maxUnavailable: 1
      type: OnDelete

  建议使用OnDelete方式,删除某个pod后,进行更新,查看没问题后,全部更新。【灰度更新方式】

 

 

十、HPA(水平pod扩缩容)

 

 

 

 

 

 

10.1 HPA实践

DaemonSet无法自动扩缩容,他的初衷就是每个node部署一个。

1、创建deloyment

kubectl create deployment nginx-server-hpa  --image=nginx:1.15.2 --port=80 --dry-run=client -o yaml>hpa-deloy.yaml

  

2、增加reources

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx-server-hpa
  name: nginx-server-hpa
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-server-hpa
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-server-hpa
    spec:
      containers:
      - image: nginx:1.15.2
        name: nginx
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 10m
status: {}

  

3、暴露服务

[root@k8s-master01 ~/k8s]# kubectl expose deployment nginx-server-hpa --port=80
service/nginx-server-hpa exposed

  

4、查看服务并访问

[root@k8s-master01 ~/k8s]# kubectl get svc
NAME               TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)   AGE
kubernetes         ClusterIP   192.168.0.1       <none>        443/TCP   24d
nginx              ClusterIP   None              <none>        80/TCP    2d13h
nginx-server-hpa   ClusterIP   192.168.166.198   <none>        80/TCP    5s

  

 

 

 

 

 5、创建hpa

[root@k8s-master01 ~/k8s]# kubectl autoscale deployment nginx-server-hpa --cpu-percent=10 --min=1 --max=10
horizontalpodautoscaler.autoscaling/nginx-server-hpa autoscaled

  

查看hpa

[root@k8s-master01 ~/k8s]# kubectl get hpa
NAME               REFERENCE                     TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
nginx-server-hpa   Deployment/nginx-server-hpa   <unknown>/10%   1         10        0          6s

  

再次查看

[root@k8s-master01 ~/k8s]# kubectl get hpa
NAME               REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx-server-hpa   Deployment/nginx-server-hpa   0%/10%    1         10        1          78s

  

 

 

 

 

 

10.2 HPA注意事项

注意事项:
1、必须安装metrics-server或其他自定义metrics-server
2、必须配置requests参数
3、不能扩容无法缩放的对象,比如DaemonSet
4、要考虑压力的根本原因,假如是后端的瓶颈,我们扩容front,是没有作用的。
      此时,需要后端提供压力接口才能进行扩缩容。

  

 十一、服务发布

11.1 label和selector

Label:对k8s中各种资源进行分类、分组,添加一个具有特别属性的一个标签。

Selector:通过一个过滤的语法进行查找到对应标签的资源

 

11.2 label操作

#创建标签
 kubectl label pods nginx unhealthy=true

#修改标签
kubectl label --overwrite pods nginx status=unhealthy

#删除标签
kubectl label pods nginx app-

#过滤资源
 kubectl get pods -l 'app in (nginx,nginx-server-hpa)' -owide --show-labels

 kubectl get pods -l 'app in (nginx,nginx-server-hpa)',controller-revision-hash!=web-cdd4c789b -owide --show-labels

  

11.3 service

在k8s中,service用于东西流量的实现,而南北流量则是通过ingress实现。

 

 

11.3.1 service定义

Service可以简单的理解为逻辑上的一组Pod。一种可以访问Pod的策略,而且其他Pod可以通过这个Service访问到这个Service代理的Pod。相对于Pod而言,它会有一个固定的名称,一旦创建就固定不变。

service创建后,同时会创建一个同名的EP(endpoint),也就是podIP:port的记录,记录了service调度到后端的信息。

11.3.2 创建一个service

# cat nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-svc
  name: nginx-svc
spec:
  ports:
  - name: http # Service端口的名称
    port: 80 # Service自己的端口, servicea --> serviceb http://serviceb,  http://serviceb:8080 
    protocol: TCP # UDP TCP SCTP default: TCP
    targetPort: 80 # 后端应用的端口
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    app: nginx
  sessionAffinity: None
  type: ClusterIP

  

11.3.3 为什么要有service?

访问服务时,我们可以通过svc直接访问后端的pod,因为pod经常创建和删除,为了保证服务一直连接,而不关心后端pod,所以引进了svc。

service  ==> endpoint  ==> pod

 

11.3.4 使用Service代理k8s外部应用

使用场景:

  • 希望在生产环境中使用某个固定的名称而非IP地址进行访问外部的中间件服务
  • 希望Service指向另一个Namespace中或其他集群中的服务
  • 某个项目正在迁移至k8s集群,但是一部分服务仍然在集群外部,此时可以使用service代理至k8s集群外部的服务

 通过service反代外部服务,我们可以统一配置文件,即使从外部迁移到容器内部,也不需要修改配置文件,只需要修改EP的地址!非常方便。

# cat nginx-svc-external.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external
spec:
  ports:
  - name: http # Service端口的名称
    port: 80 # Service自己的端口, servicea --> serviceb http://serviceb,  http://serviceb:8080 
    protocol: TCP # UDP TCP SCTP default: TCP
    targetPort: 8081 # 后端应用的端口
  sessionAffinity: None
  type: ClusterIP

#创建好了svc后,ep不会自动创建,需要我们手动创建一个ep,指向后端代理的服务。我们这里使用baidu的地址来测试。
# cat nginx-ep-external.yaml 
apiVersion: v1
kind: Endpoints
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external
  namespace: default
subsets:
- addresses:
  - ip: 140.205.94.189 
  ports:
  - name: http
    port: 8081
    protocol: TCP

  

测试:

 

 

 

 

11.3.5 使用Service代理域名

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-externalname
  name: nginx-externalname
spec:
  type: ExternalName
  externalName: www.baidu.com

  注意:说明: ExternalName 服务接受 IPv4 地址字符串,但作为包含数字的 DNS 名称,而不是 IP 地址。实测下来,这里使用IP地址不行

11.3.6 service的常见类型

  • ClusterIP:在集群内部使用,也是默认值。
  • ExternalName:通过返回定义的CNAME别名。一定要使用域名!
  • NodePort:在所有安装了kube-proxy的节点上打开一个端口,此端口可以代理至后端Pod,然后集群外部可以使用节点的IP地址和NodePort的端口号访问到集群Pod的服务。NodePort端口范围默认是30000-32767。
  • LoadBalancer:使用云提供商的负载均衡器公开服务。

 

11.4 Ingress

11.4.1 Ingress安装

通俗来讲,ingress和之前提到的Service、Deployment,也是一个k8s的资源类型,ingress用于实现用域名的方式访问k8s内部应用。

首先安装helm管理工具:https://helm.sh/docs/intro/install/

使用helm安装ingress:https://kubernetes.github.io/ingress-nginx/deploy/#using-helm

添加ingress的helm仓库(课程讲解的版本已经上传至百度网盘)

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

下载ingress的helm包至本地

helm pull ingress-nginx/ingress-nginx

 

tar xf ingress-nginx-3.6.0.tgz

cd ingress-nginx

vim values.yaml

 

更改对应的配置

  • a) Controller和admissionWebhook的镜像地址,需要将公网镜像同步至公司内网镜像仓库(和课程不一致的版本,需要自行同步gcr镜像的,可以百度查一下使用阿里云同步gcr的镜像,也可以参考这个连接https://blog.csdn.net/weixin_39961559/article/details/80739352,或者参考这个连接: https://blog.csdn.net/sinat_35543900/article/details/103290782)
  • b) hostNetwork设置为true
  • c)  dnsPolicy设置为 ClusterFirstWithHostNet
  • d)  NodeSelector添加ingress: "true"部署至指定节点
  • e)  类型更改为kind: DaemonSet

部署ingress

给需要部署ingress的节点上打标签

kubectl label node k8s-master03 ingress=true

kubectl create ns ingress-nginx

helm install ingress-nginx -n ingress-nginx .

  

 

 

  1. 将ingress controller部署至Node节点(ingress controller不能部署在master节点,需要安装视频中的步骤将ingress controller部署至Node节点,生产环境最少三个ingress controller,并且最好是独立的节点)

kubectl label node k8s-node01 ingress=true

kubectl label node k8s-master03 ingress-

 

 

 

11.4.2 Ingress入门使用

apiVersion: networking.k8s.io/v1beta1 # networking.k8s.io/v1 / extensions/v1beta1 
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
  name: example
spec:
  rules: # 一个Ingress可以配置多个rules
  - host: foo.bar.com # 域名配置,可以不写,匹配*, *.bar.com
    http:
      paths: # 相当于nginx的location配合,同一个host可以配置多个path / /abc
      - backend:
          serviceName: nginx-svc
          servicePort: 80
        path: /
  - host: foo2.bar.com # 域名配置,可以不写,匹配*, *.bar.com
    http:
      paths: # 相当于nginx的location配合,同一个host可以配置多个path / /abc
      - backend:
          serviceName: nginx-externalname
          servicePort: 80
        path: /test

  

说明:

  • 配置了2个主机,一个后端服务是nginx-svc,另一个后端服务是nginx-externalname
  • 确保后端服务都是可用的
  • 本地测试,在本机上写hosts,hosts为ingress的主机ip
#ingress-nginx所在机器的ip
10.10.2.129 foo.bar.com 10.10.2.129 foo2.bar.com

  

验证:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

集群级别的资源,没有命名空间隔离。

classrole

classrolebinding

storageclass

ingressclass


posted @ 2022-10-13 11:50  skyflask  阅读(52)  评论(0编辑  收藏  举报