K8s部署及服务总结

K8s学习

一、 kubernetes 概述

1 、 kubernetes 基本介绍

​ kubernetes,简称 K8s,是用 8 代替 8 个字符“ubernete”而成的缩写。是一个开源
的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的
应用简单并且高效(powerful),Kubernetes 提供了应用部署,规划,更新,维护的一种
机制。
​ 传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配
置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等
操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于
可移植性。
​ 新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件
系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,
由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进
行迁移。
​ 容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间
成一对一关系也使容器有更大优势,使用容器可以在 build 或 release 的阶段,为应用创
建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,
这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更“透明”,
这更便于监控和管理。
​ Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、
应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便
对应用请求进行负载均衡。
​ 在 Kubernetes 中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通
过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需
要运维人员去进行复杂的手工配置和处理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njDV8NL2-1641264633446)(K8s学习.assets/02-第一部分 概述特性和架构组件.png)]

二、探针机制

1. 探针介绍

探针有两种类型:存活探针和就绪探针。

Kubelet使用liveness probe(存活探针)来确定何时重启容器。当应用程序处于运行状态但无法做进一步操作,liveness探针将捕获到deadlock,重启处于该状态下的容器,使应用程序在存在bug的情况下依然能够继续运行下去。

Kubelet使用readiness probe(就绪探针)来确定容器是否已经就绪可以接受流量。只有当Pod中的容器都处于就绪状态时kubelet才会认定该Pod处于就绪状态。该信号的作用是控制哪些Pod应该作为service的后端。如果Pod处于非就绪状态,那么它们将会被从service的load balancer中移除。

2. 定义 liveness命令

Liveness探针有三种检测方式,分别是exec方式、http方式和tcp方式。

1. 定义一个exec的liveness探针案例

apiVersion: v1

kind: Podmetadata:

 labels:

  test: liveness

 name: liveness-execspec:

 containers:

 \- name: liveness

  args:

  \- /bin/sh

  \- -c

  \- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600

  image: gcr.io/google_containers/busybox

  livenessProbe:

   exec:

​    command:

​    \- cat

​    \- /tmp/healthy

   initialDelaySeconds: 5

   periodSeconds: 5

该配置文件给Pod配置了一个容器。periodSeconds 规定kubelet要每隔5秒执行一次liveness probe。 initialDelaySeconds 告诉kubelet在第一次执行probe之前要的等待5秒钟。探针检测命令是在容器中执行 cat /tmp/healthy 命令。如果命令执行成功,将返回0,kubelet就会认为该容器是活着的并且很健康。如果返回非0值,kubelet就会杀掉这个容器并重启它。

容器启动时,执行命令:

/bin/sh -c “touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600”

在容器生命的最初30秒内有一个 /tmp/healthy 文件,在这30秒内 cat /tmp/healthy命令会返回一个成功的返回码。30秒后, cat /tmp/healthy 将返回失败的返回码。

2. 定义一个HTTPliveness探针案例

apiVersion: v1kind: Podmetadata:

 labels:

  test: liveness

 name: liveness-httpspec:

 containers:

 \- name: liveness

  args:

  \- /server

  image: gcr.io/google_containers/liveness

  livenessProbe:

   httpGet:

​    path: /healthz

​    port: 8080

​    httpHeaders:

​     \- name: X-Custom-Header

​      value: Awesome

   initialDelaySeconds: 3

   periodSeconds: 3

该配置文件只定义了一个容器,livenessProbe 指定kubelete需要每隔3秒执行一次liveness probe。initialDelaySeconds 指定kubelet在该执行第一次探测之前需要等待3秒钟。该探针将向容器中的server的8080端口发送一个HTTP GET请求。如果server的/healthz路径的handler返回一个成功的返回码,kubelet就会认定该容器是活着的并且很健康。如果返回失败的返回码,kubelet将杀掉该容器并重启它。

任何大于200小于400的返回码都会认定是成功的返回码。其他返回码都会被认为是失败的返回码。

3. 定义一个TCPliveness探针案例

第三种liveness probe使用TCP Socket。 使用此配置,kubelet将尝试在指定端口上打开容器的套接字。 如果可以建立连接,容器被认为是健康的,如果不能就认为是失败的。

TCP检查的配置与HTTP检查非常相似。 此示例同时使用了readiness和liveness probe。 容器启动后5秒钟,kubelet将发送第一个readiness probe。 这将尝试连接到端口8080上的goproxy容器。如果探测成功,则该pod将被标记为就绪。Kubelet将每隔10秒钟执行一次该检查。

除了readiness probe之外,该配置还包括liveness probe。 容器启动15秒后,kubelet将运行第一个liveness probe。 就像readiness probe一样,这将尝试连接到goproxy容器上的8080端口。如果liveness probe失败,容器将重新启动。

使用命名的端口

可以使用命名的ContainerPort作为HTTP或TCP liveness检查:

ports:

\- name: liveness-port

  containerPort: 8080

  hostPort: 8080

livenessProbe:

 httpGet:

 path: /healthz

 port: liveness-port

3. 定义readiness探针

应用程序有时暂时无法对外部流量提供服务。 例如,应用程序可能需要在启动期间加载大量数据或配置文件。 在这种情况下,在不杀死应用程序,也不想发送请求的情况下。可以使用readiness probe来检测和减轻这些情况。 Pod中的容器可以报告自己还没有准备,不能处理Kubernetes服务发送过来的流量。

Readiness probe的配置跟liveness probe很像。唯一的不同是使用 readinessProbe而不是livenessProbe,检测方式也是相同,有三种方式。

readinessProbe:

 exec:

  command:

  \- cat

  \- /tmp/healthy

 initialDelaySeconds: 5

 periodSeconds: 5

Readiness probe的HTTP和TCP的探测器配置跟liveness probe一样。

Readiness和livenss probe可以并行用于同一容器。 使用两者可以确保流量无法到达未准备好的容器,并且容器在失败时重新启动。

4. 配置Probe参数

Probe中有很多精确和详细的配置,通过它们你能准确的控制liveness和readiness检查:

· initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。

· periodSeconds:执行探测的频率。默认是10秒,最小1秒。

· timeoutSeconds:探测超时时间。默认1秒,最小1秒。

· successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。

· failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。

HTTP probe中可以给 httpGet设置其他配置项:

· host:连接的主机名,默认连接到pod的IP。你可能想在http header中设置”Host”而不是使用IP。

· scheme:连接使用的schema,默认HTTP。

· path: 访问的HTTP server的path。

· httpHeaders:自定义请求的header。HTTP运行重复的header。

· port:访问的容器的端口名字或者端口号。端口号必须介于1和65525之间。

对于HTTP探测器,kubelet向指定的路径和端口发送HTTP请求以执行检查。 Kubelet将probe发送到容器的IP地址,除非地址被httpGet中的可选host字段覆盖。

三、K8s容器亲和性

1. Node Affinity

Affinity 翻译成中文是“亲和性”,它对应的是 Anti-Affinity,我们翻译成“互斥”。这两个词比较形象,可以把 pod 选择 node 的过程类比成磁铁的吸引和互斥,不同的是除了简单的正负极之外,pod 和 node 的吸引和互斥是可以灵活配置的。

Affinity的优点:

· 匹配有更多的逻辑组合,不只是字符串的完全相等

· 调度分成软策略(soft)和硬策略(hard),在软策略下,如果没有满足调度条件的节点,pod会忽略这条规则,继续完成调度。

目前主要的node affinity:

(1)requiredDuringSchedulingIgnoredDuringExecution
表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中IgnoreDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,pod也会继续运行。

(2)requiredDuringSchedulingRequiredDuringExecution
表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中RequiredDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,则重新选择符合要求的节点。

(3)preferredDuringSchedulingIgnoredDuringExecution
表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。

(4)preferredDuringSchedulingRequiredDuringExecution
表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。其中RequiredDuringExecution表示如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点。

这里的匹配逻辑是label在某个列表中,可选的操作符有:

· In: label的值在某个列表中

· NotIn:label的值不在某个列表中

· Exists:某个label存在

· DoesNotExist:某个label不存在

· Gt:label的值大于某个值(字符串比较)

· Lt:label的值小于某个值(字符串比较)

案例:

affinity:

​    podAntiAffinity:

​     requiredDuringSchedulingIgnoredDuringExecution:

​      \- labelSelector:

​        matchExpressions:

​         \- key: "role"

​          operator: In

​          values:

​          \- coordinator

​       topologyKey: "kubernetes.io/hostname"

​    nodeAffinity:

​     requiredDuringSchedulingIgnoredDuringExecution:

​      nodeSelectorTerms: 

​       \- matchExpressions:

​         \- key: "kubernetes.io/hostname"

​          operator: In

​          values:

​          \- jfimpala017

​          \- jfimpala019

四、语法案例

 apiVersion: v1
kind: Service
matadata:                        # 元数据
  name: string                   # service的名称
  namespace: string              # 命名空间  
  labels:                        # 自定义标签属性列表
    - name: string                 
  annotations:                   # 自定义注解属性列表  
    - name: string                 
spec:                            # 详细描述
  selector: []                   # label selector配置,将选择具有label标签的Pod作为管理 
  type: string                   # service的类型,指定service的访问方式,默认为
  clusterIP: string              # 虚拟服务地址      
  sessionAffinity: string        # 是否支持session
  ports:                         # service需要暴露的端口列表

  - name: string                 # 端口名称
    protocol: string             # 端口协议,支持TCP和UDP,默认TCP
    port: int                    # 服务监听的端口号
    targetPort: int              # 需要转发到后端Pod的端口号
    nodePort: int                # 当type = NodePort时,指定映射到物理机的端口号
      status:                        # 当spce.type=LoadBalancer时,设置外部负载均衡器的地址
    loadBalancer:                # 外部负载均衡器    
      ingress:                   # 外部负载均衡器 
        ip: string               # 外部负载均衡器的Ip地址值
        hostname: string         # 外部负载均衡器的主机名
      externalTrafficPolicy: Local   # 与主机ip端口绑定在一起,即该主机的该端口只与该命名空间下的选择这个server的pod通信

---

apiVersion: extensions/v1beta1   #接口版本
kind: Deployment                 #接口类型
metadata:
  name: ptengine-demo               #Deployment名称
  namespace: ptengine-prd           #namespace 名称
  labels:
    app: ptengine-demo              #标签
spec:
  replicas: 3
   strategy:
    rollingUpdate:  ##由于replicas为3,则整个升级,pod个数在2-4个之间
      maxSurge: 1       #滚动升级时会先启动1个pod
      maxUnavailable: 1 #滚动升级时允许的最大Unavailable的pod个数
  template:         
    metadata:
      labels:
        app: ptengine-demo  #模板名称必填
    sepc: #定义容器模板,该模板可以包含多个容器
      containers:                                                                   
        - name: ptengine-demo                                                           #镜像名称
          image: reg.pt1.com/ptengine-prd/ptengine-demo:0.0.1-SNAPSHOT #镜像地址
          CMD: [ "/bin/sh","-c","cat /etc/config/path/to/special-key" ]    #启动CMD
          args:                                                                #启动参数
            - '-storage.local.retention=$(STORAGE_RETENTION)'
            - '-web.external-url=$(EXTERNAL_URL)'
          imagePullPolicy: IfNotPresent  #如果不存在则拉取
          livenessProbe:       #表示container是否处于live状态。如果LivenessProbe失败,LivenessProbe将会通知kubelet对应的container不健康了。随后kubelet将kill掉container,并根据RestarPolicy进行进一步的操作。默认情况下LivenessProbe在第一次检测之前初始化值为Success,如果container没有提供LivenessProbe,则也认为是Success;
            httpGet:
              path: /health #如果没有心跳检测接口就为/
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 60 ##启动后延时多久开始运行检测
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 5
            readinessProbe:
          readinessProbe:
            httpGet:
              path: /health #如果没有健康检测接口就为/
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 30 ##启动后延时多久开始运行检测
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 5
          resources:              ##CPU内存限制
            requests:
              cpu: 2
              memory: 2048Mi
            limits:
              cpu: 2
              memory: 2048Mi
          env:                    ##通过环境变量的方式,直接传递pod=自定义Linux OS环境变量
            - name: LOCAL_KEY     #本地Key
              value: value
            - name: CONFIG_MAP_KEY  #local策略可使用configMap的配置Key,
              valueFrom:
                configMapKeyRef:
                  name: special-config   #configmap中找到name为special-config
                  key: special.type      #找到name为special-config里data下的key
          ports:
            - name: http
              containerPort: 8080 #对service暴露端口
          volumeMounts:     #挂载volumes中定义的磁盘
          - name: log-cache
            mount: /tmp/log
          - name: sdb       #普通用法,该卷跟随容器销毁,挂载一个目录
            mountPath: /data/media    
          - name: nfs-client-root    #直接挂载硬盘方法,如挂载下面的nfs目录到/mnt/nfs
            mountPath: /mnt/nfs
          - name: example-volume-config  #高级用法第1种,将ConfigMap的log-script,backup-script分别挂载到/etc/config目录下的一个相对路径path/to/...下,如果存在同名文件,直接覆盖。
            mountPath: /etc/config       
          - name: rbd-pvc                #高级用法第2中,挂载PVC(PresistentVolumeClaim)

#使用volume将ConfigMap作为文件或目录直接挂载,其中每一个key-value键值对都会生成一个文件,key为文件名,value为内容,
  volumes:  # 定义磁盘给上面volumeMounts挂载

  - name: log-cache
    emptyDir: {}
  - name: sdb  #挂载宿主机上面的目录
    hostPath:
      path: /any/path/it/will/be/replaced
  - name: example-volume-config  # 供ConfigMap文件内容到指定路径使用
    configMap:
      name: example-volume-config  #ConfigMap中名称
      items:
      - key: log-script           #ConfigMap中的Key
        path: path/to/log-script  #指定目录下的一个相对路径path/to/log-script
      - key: backup-script        #ConfigMap中的Key
        path: path/to/backup-script  #指定目录下的一个相对路径path/to/backup-script
  - name: nfs-client-root         #供挂载NFS存储类型
    nfs:
      server: 10.42.0.55          #NFS服务器地址
      path: /opt/public           #showmount -e 看一下路径
  - name: rbd-pvc                 #挂载PVC磁盘
    persistentVolumeClaim:
      claimName: rbd-pvc1         #挂载已经申请的pvc磁盘



#单个pod的语法,与控制器类型的pod语法相似,可互用
apiVersion: v1       #必选,版本号,例如v1
kind: Pod       #必选,Pod
metadata:       #必选,元数据
  name: string       #必选,Pod名称
  namespace: string    #必选,Pod所属的命名空间
  labels:      #自定义标签
    - name: string     #自定义标签名字
  annotations:       #自定义注释列表
    - name: string
spec:         #必选,Pod中容器的详细定义
  containers:      #必选,Pod中容器列表

  - name: string     #必选,容器名称
    image: string    #必选,容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]    #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]     #容器的启动命令参数列表
    workingDir: string     #容器的工作目录
    volumeMounts:    #挂载到容器内部的存储卷配置
    - name: string     #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string    #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean    #是否为只读模式
      ports:       #需要暴露的端口库号列表
    - name: string     #端口号名称
      containerPort: int   #容器需要监听的端口号
      hostPort: int    #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string     #端口协议,支持TCP和UDP,默认TCP
      env:       #容器运行前需设置的环境变量列表
    - name: string     #环境变量名称
      value: string    #环境变量的值
      resources:       #资源限制和请求的设置
      limits:      #资源限制的设置
        cpu: string    #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string     #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests:      #资源请求的设置
        cpu: string    #Cpu请求,容器启动的初始可用数量
        memory: string     #内存清楚,容器启动的初始可用数量
      livenessProbe:     #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:      #对Pod容器内检查方式设置为exec方式
        command: [string]  #exec方式需要制定的命令或脚本
      httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
          tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
             port: number
           initialDelaySeconds: 0  #容器启动完成后首次探测的时间,单位为秒
           timeoutSeconds: 0   #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
           periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
           successThreshold: 0
           failureThreshold: 0
           securityContext:
             privileged:false
          restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
          nodeSelector: obeject  #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
          imagePullSecrets:    #Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
      hostNetwork:false      #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
      volumes:       #在该pod上定义共享存储卷列表
    - name: string     #共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}     #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string     #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string     #Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:      #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string  
        items:     
        - key: string
          path: string
          configMap:     #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
            name: string
            items:
        - key: string

五、K8s集群部署

1.卸载k8s组件

在卸载K8s组件前,先执行kubeadm reset命令,清空K8s集群设置

kubeadm reset
卸载管理组件

yum erase -y kubelet kubectl kubeadm kubernetes-cni
删除基础组件镜像。基础组件通过Docker镜像部署,因此只需要强制删除对应镜像即可卸载。

docker rmi -f k8s.gcr.io/kube-apiserver:v1.15.1

docker rmi -f k8s.gcr.io/kube-controller-manager:v1.15.1

docker rmi -f k8s.gcr.io/kube-scheduler:v1.15.1

docker rmi -f k8s.gcr.io/kube-proxy:v1.15.1

docker rmi -f k8s.gcr.io/pause:3.1

docker rmi -f k8s.gcr.io/etcd:3.3.10

docker rmi -f k8s.gcr.io/coredns:1.3.1

2.卸载Docker

杀死docker有关的容器:

docker kill $(docker ps -a -q)
删除所有docker容器:

docker rm $(docker ps -a -q)
删除所有docker镜像:

docker rmi $(docker images -q)
停止 docker 服务:

systemctl stop docker
删除docker相关存储目录:

rm -rf /etc/docker
rm -rf /run/docker
rm -rf /var/lib/dockershim
rm -rf /var/lib/docker
如果删除不掉,则先umount:

umount /var/lib/docker/devicemapper
然后再重新执行上面那步“删除docker相关存储目录”。

经过上面一系列准备后,我们终于到了最后环节,开始删除docker。

查看系统已经安装了哪些docker包:

[root@localhost ~]# yum list installed | grep docker
containerd.io.x86_64 1.2.13-3.2.el7 @docker-ce-stable
docker-ce.x86_64 3:19.03.12-3.el7 @docker-ce-stable
docker-ce-cli.x86_64 1:19.03.12-3.el7 @docker-ce-stable
卸载相关包:

[root@localhost ~]# yum remove containerd.io.x86_64 docker-ce.x86_64 docker-ce-cli.x86_64
接着会出现选择提示,直接输入“y”然后回车就可以。

注意,卸载相关包的时候,是要根据上面查询出来的包名对应上去。我是通过“yum list installed | grep docker”命令搜索出我这边安装了以下包:

containerd.io.x86_64

docker-ce.x86_64

docker-ce-cli.x86_64

所以我删除的时候,是直接一次性删除三个,拼接成以下命令:

yum remove containerd.io.x86_64 docker-ce.x86_64 docker-ce-cli.x86_64

到时大家根据自己的实际情况来删除即可。

执行完上述操作后,我们重新执行以下命令,看是否已经成功删除:

yum list installed | grep docker
不再出现相关信息,证明删除成功,再看看docker命令:

[root@localhost ~]# docker version
-bash: /usr/bin/docker: No such file or directory
因此,成功卸载Docker

3.Kubernetes集群升级(kubeadm升级方式)

参考:(128条消息) Kubernetes集群升级(kubeadm升级方式)_???111的博客-CSDN博客

1、升级前的版本确认(相同的大版本号下的小版本升级还是跨版本升级)

例如:从1.12.0升级到1.12.7 或者 从1.12.7升级到1.13.0

2、配置kubernetes安装源(已配置kubernetes源,此处跳过)

Debian/Ubuntu添加源方式:

apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - 
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF  
apt-get update
apt-get install -y kubelet kubeadm kubectl

CentOS/RHEL/Fedora添加源方式:

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet

注意:如果需要安装特定版本,请参照如下方式

查看版本:
yum --enablerepo=kubernetes list kubelet kubeadm kubectl --showduplicates | sort -r

安装特定版本
yum --enablerepo=kubernetes install kubelet-1.17.0-0 kubeadm-1.17.0-0 kubectl-1.17.0-0

3、验证安装的版本

kubeadm version

4、查看升级后的所需镜像

kubeadm config images list

这里可以提前下载好镜像
kubeadm config images list > images.txt
for i in `cat images.txt`; do docker pull $i; done

5、在主节点上运行如下命令(此命令检查您的群集是否可以升级,并获取可以升级到的版本)

kubeadm upgrade plan

6、选择要升级到的版本,然后运行相应的命令(此处从1.12.7版本升级到1.13.0)

kubeadm upgrade apply v1.13.0

7、将控制节点设置为不可调度

kubectl drain $NODE --ignore-daemonsets

8、重启控制节点的kubelet服务

systemctl daemon-reload
systemctl restart kubelet

9、逐一将除控制节点以外的其他需要升级的节点设置为不可调度

kubectl cordon $NODENAME
kubectl drain $NODENAME

9、在除控制节点的所有节点上逐一执行如下命令升级(注意执行如下命令前,需要先按照步骤2的方法升级程序包)

kubeadm upgrade node config --kubelet-version v1.13.0

10、重新启动升级后节点的kubelet服务

systemctl daemon-reload
systemctl restart kubelet

11、恢复节点为可调度(在控制节点上操作)

kubectl uncordon $NODE

参考:https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade-1-13/

转载于:https://www.cnblogs.com/a120608yby/p/10684296.html

4.、 kubernetes 集群搭建( kubeadm 方式 )

1、 前置知识点

目前生产部署 Kubernetes 集群主要有两种方式:
(1)kubeadm
Kubeadm 是一个 K8s 部署工具,提供 kubeadm init 和 kubeadm join,用于快速部
署 Kubernetes 集群。
官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
(2)二进制包
从 github 下载发行版的二进制包,手动部署每个组件,组成 Kubernetes 集群。
Kubeadm 降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可
控,推荐使用二进制包部署 Kubernetes 集群,虽然手动部署麻烦点,期间可以学习很
多工作原理,也利于后期维护。

2 、kubeadm 部署方式介绍

kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具,这个工具能通
过两条指令完成一个 kubernetes 集群的部署:
第一、创建一个 Master 节点 kubeadm init
第二, 将 Node 节点加入到当前集群中 $ kubeadm join <Master 节点的 IP 和端口 >

3 、安装要求

在开始之前,部署 Kubernetes 集群机器需要满足以下几个条件:

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
  • 硬件配置:2GB 或更多 RAM,2 个 CPU 或更多 CPU,硬盘 30GB 或更多
  • 集群中所有机器之间网络互通
  • 可以访问外网,需要拉取镜像
  • 禁止 swap 分区

4 、系统初始化

4.1 关闭防火墙:

$ systemctl stop firewalld
$ systemctl disable firewalld

4.2 关闭 selinux:

$ sed -i ‘s/enforcing/disabled/’ /etc/selinux/config # 永久
$ setenforce 0 # 临时

4.3 关闭 swap:

$ swapoff -a # 临时
$ vim /etc/fstab # 永久

4.4 主机名:

$ hostnamectl set-hostname

4.5 在 master 添加 hosts:

$ cat >> /etc/hosts << EOF
192.168.31.61 k8s-master
192.168.31.62 k8s-node1
192.168.31.63 k8s-node2
EOF

4.6 将桥接的 IPv4 流量传递到 iptables 的链:

$ cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sysctl --system # 生效

4.7 时间同步:

$ yum install ntpdate -y
$ ntpdate time.windows.com

5、所有节点安装 Docker/kubeadm/kubelet

Kubernetes 默认 CRI(容器运行时)为 Docker,因此先安装 Docker。

(1)安装 Docker

$ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
$ yum -y install docker-ce-18.06.1.ce-3.el7
$ systemctl enable docker && systemctl start docker
$ docker --version

(2)添加阿里云 YUM 软件源

设置仓库地址

cat > /etc/docker/daemon.json << EOF

{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF

(3) 新增kubernetes源

[root@master ~]# cat < /etc/yum.repos.d/kubernetes.repo

[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

[] 中括号中的是repository id,唯一,用来标识不同仓库
name 仓库名称,自定义
baseurl 仓库地址
enable 是否启用该仓库,默认为1表示启用
gpgcheck 是否验证从该仓库获得程序包的合法性,1为验证
repo_gpgcheck 是否验证元数据的合法性 元数据就是程序包列表,1为验证
gpgkey=URL 数字签名的公钥文件所在位置,如果gpgcheck值为1,此处就需要指定gpgkey文件的位置,如果gpgcheck值为0就不需要此项了

更新缓存
[root@master ~]# yum clean all

[root@master ~]# yum -y makecache

(4)安装kubelet

查看版本:
yum --enablerepo=kubernetes list kubelet kubeadm kubectl --showduplicates | sort -r

安装特定版本
yum --enablerepo=kubernetes install kubelet-1.17.1-0 kubeadm-1.17.1-0 kubectl-1.17.1-0

systemctl enable kubelet && systemctl start kubelet

6、部署 Kubernetes Master

每次重启服务时需:kubeadm reset

(1)在 192.168.241.139(Master)执行

kubeadm init
–apiserver-advertise-address=192.168.241.129
–image-repository registry.aliyuncs.com/google_containers
–kubernetes-version v1.17.1
–service-cidr=10.1.0.0/16
–pod-network-cidr=10.244.0.0/16

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iTFlYHTn-1641264633449)(K8s学习.assets/image-20211222154108652.png)]

将当前用户配置为集群管理员(如果不配置,下次连接时会无法使用kubectl)

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

部署flannel

 kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

7、Node节点安装

1.安装kubelet、kubeadm和kubectl

同master节点

2.下载镜像

同master节点

3.加入集群

以下操作master上执行

3.1 查看令牌

[root@master ~]# kubeadm token list
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
j5eoyz.zu0x6su7wzh752b3 2019-06-04T17:40:41+08:00 authentication,signing The default bootstrap token generated by ‘kubeadm init’. system:bootstrappers:kubeadm:default-node-token
发现之前初始化时的令牌已过期

3.2 生成新的令牌

[root@master ~]# kubeadm token create
1zl3he.fxgz2pvxa3qkwxln

3.3 生成新的加密串

[root@master ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null |
openssl dgst -sha256 -hex | sed ‘s/^.* //’

3.4 node节点加入集群

在node节点上分别执行如下操作:

kubeadm join --token y2sv1g.tcd4a3oqdkvrdqnz --discovery-token-ca-cert-hash sha256:be750378aab8c32a635aff8ada8a0626a17f9371d62fc8252b7620382f5a742e 192.168.241.129:6443

加入完毕后,我们用命令kubectl get nodes获取所有节点

[root@k8s-master ~]# kubectl get nodes
NAME         STATUS     ROLES    AGE    VERSION
k8s-master   Ready      master   115m   v1.15.9
k8s-node1    NotReady   <none>   111m   v1.15.9
k8s-node2    Ready      <none>   111m   v1.15.9

验证安装信息

检查系统基础模块健康度
[root@k8s-master ~]# kubectl get componentstatus
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-0               Healthy   {"health":"true"}  
检查node状态,如果有工作节点NotReady,等几分钟一般就会正常
[root@k8s-master ~]# kubectl get nodes
NAME         STATUS     ROLES    AGE    VERSION
k8s-master   Ready      master   115m   v1.15.9
k8s-node1    NotReady   <none>   111m   v1.15.9
k8s-node2    Ready      <none>   111m   v1.15.9
检查系统pod状态
[root@k8s-master ~]# kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-94d74667-l8lqt               1/1     Running   0          115m
coredns-94d74667-svgrk               1/1     Running   0          115m
etcd-k8s-master                      1/1     Running   0          115m
kube-apiserver-k8s-master            1/1     Running   0          114m
kube-controller-manager-k8s-master   1/1     Running   0          115m
kube-flannel-ds-amd64-64zsm          1/1     Running   0          2m5s
kube-flannel-ds-amd64-csb8h          1/1     Running   0          2m5s
kube-flannel-ds-amd64-nfcsh          1/1     Running   0          2m5s
kube-proxy-b669n                     1/1     Running   0          112m
kube-proxy-d84cb                     1/1     Running   0          115m
kube-proxy-w7tv7                     1/1     Running   0          111m
kube-scheduler-k8s-master            1/1     Running   0          115m

8、测试 kubernetes 集群

在 Kubernetes 集群中创建一个 pod,验证是否正常运行:
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pod,svc
访问地址:http://NodeIP:Port

删除app

kubectl delete pods nginx-86c57db685-45wgx

查看详细

kubectl get pods -o wide

192.168.241.129:31236

9、部署 Dashboard

[root@k8s-master ~]# wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

[root@k8s-master ~]# vim kubernetes-dashboard.yaml
修改内容:
109     spec:
110       containers:
111       - name: kubernetes-dashboard
112         image: lizhenliang/kubernetes-dashboard-amd64:v1.10.1   # 修改此行

......

157 spec:
158   type: NodePort     # 增加此行
159   ports:
160     - port: 443
161       targetPort: 8443
162       nodePort: 30001   # 增加此行
163   selector:
164     k8s-app: kubernetes-dashboard

[root@k8s-master ~]# kubectl apply -f kubernetes-dashboard.yaml

在火狐浏览器访问(google受信任问题不能访问)地址:192.168.241.139:30001

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ae4y1DnE-1641264633451)(K8s学习.assets/image-20211222210428560.png)]

[root@k8s-master ~]# kubectl create serviceaccount dashboard-admin -n kube-system
serviceaccount/dashboard-admin created
[root@k8s-master ~]# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin
--serviceaccount=kube-system:dashboard-admin
[root@k8s-master ~]# kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
Name:         dashboard-admin-token-d9jh2
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: dashboard-admin
              kubernetes.io/service-account.uid: 4aa1906e-17aa-4880-b848-8b3959483323

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  11 bytes
token:      eyJhbGciOiJ...(省略如下)...AJdQ

token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZDlqaDIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNGFhMTkwNmUtMTdhYS00ODgwLWI4NDgtOGIzOTU5NDgzMzIzIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.OkF6h7tVQqmNJniCHJhY02G6u6dRg0V8PTiF8xvMuJJUphLyWlWctgmplM4kjKVZo0fZkAthL7WAV5p_AwAuj4LMfo1X5IpxUomp4YZyhqgsBM0A2ksWoKoLDjbizFwOty8TylWlsX1xcJXZjmP9OvNgjjSq5J90N5PnxYIIgwAMP3fawTP7kUXxz5WhJo-ogCijJCFyYBHoqHrgAbk9pusI8DpGTNIZxBMxkwPPwFwzNCOfKhD0c8HjhNeliKsOYLryZObRdmTQXmxsDfxynTKsRxv_EPQb99yW9GXJPQL0OwpYb4b164CFv857ENitvvKEOU6y55P9hFkuQuAJdQ

解决其他浏览器不能访问的问题

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EEN6phx5-1641264633454)(K8s学习.assets/copycode.gif)]](javascript:void(0)😉

[root@k8s-master ~]# cd /etc/kubernetes/pki/
[root@k8s-master pki]# mkdir ui
[root@k8s-master pki]# cp apiserver.crt  ui/
[root@k8s-master pki]# cp apiserver.key  ui/
[root@k8s-master pki]# cd ui/
[root@k8s-master ui]# mv apiserver.crt dashboard.pem
[root@k8s-master ui]# mv  apiserver.key   dashboard-key.pem
[root@k8s-master ui]# kubectl delete secret kubernetes-dashboard-certs -n kube-system
[root@k8s-master ui]# kubectl create secret generic kubernetes-dashboard-certs --from-file=./ -n kube-system

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DthA40MO-1641264633455)(K8s学习.assets/copycode.gif)]](javascript:void(0)😉

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uCvj2U0D-1641264633458)(K8s学习.assets/copycode.gif)]](javascript:void(0)😉

[root@k8s-master]# vim kubernetes-dashboard.yaml #回到这个yaml的路径下修改
修改 dashboard-controller.yaml 文件,在args下面增加证书两行
          - --tls-key-file=dashboard-key.pem
          - --tls-cert-file=dashboard.pem
[root@k8s-master ~]kubectl apply -f kubernetes-dashboard.yaml
[root@k8s-master ~]# kubectl create serviceaccount dashboard-admin -n kube-system
serviceaccount/dashboard-admin created
[root@k8s-master ~]# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin
--serviceaccount=kube-system:dashboard-admin
[root@k8s-master ~]# kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
Name:         dashboard-admin-token-zbn9f
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: dashboard-admin
              kubernetes.io/service-account.uid: 40259d83-3b4f-4acc-a4fb-43018de7fc19

Type:  kubernetes.io/service-account-token

Data
====
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4temJuOWYiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNDAyNTlkODMtM2I0Zi00YWNjLWE0ZmItNDMwMThkZTdmYzE5Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.E0hGAkeQxd6K-YpPgJmNTv7Sn_P_nzhgCnYXGc9AeXd9k9qAcO97vBeOV-pH518YbjrOAx_D6CKIyP07aCi_3NoPlbbyHtcpRKFl-lWDPdg8wpcIefcpbtS6uCOrpaJdCJjWFcAEHdvcfmiFpdVVT7tUZ2-eHpRTUQ5MDPF-c2IOa9_FC9V3bf6XW6MSCZ_7-fOF4MnfYRa8ucltEIhIhCAeDyxlopSaA5oEbopjaNiVeJUGrKBll8Edatc7-wauUIJXAN-dZRD0xTULPNJ1BsBthGQLyFe8OpL5n_oiHM40tISJYU_uQRlMP83SfkOpbiOpzuDT59BBJB57OQtl3w
ca.crt:     1025 bytes

1.用create命令生成yaml文件

kubectl create deployment nginx --image=nginx -o yaml --dry-run

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

kubectl get deploy nginx -o=yaml --export > m2.yaml


三、k8s服务总结

1、一次性job与定时job

容器按照持续运行的时间可分为两类:服务类容器和工作类容器。

服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等。工作类容器则是一次性任务,比如批处理程序,完成后容器就退出。

Kubernetes 的 Deployment、ReplicaSet 和 DaemonSet 都用于管理服务类容器;对于工作类容器,我们用 Job。

一、job的应用

1、编写job的yaml文件myjob.yaml:

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H99bQ8KT-1641264633460)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# cat myjob.yaml 
apiVersion:  batch/v1  
kind: Job
metadata:
  name: job
spec:
  template:
     spec:
        containers:
            - name: job
              image: reg.yunwei.com/learn/busybox:latest
              command: ["echo","hello kubernetes"]
        restartPolicy: Never

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dh2L3rOq-1641264633461)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

① batch/v1 是当前 Job 的 apiVersion。

② 指明当前资源的类型为 Job。

③ restartPolicy 指定什么情况下需要重启容器。对于 Job,只能设置为 Never 或者 OnFailure。对于其他 controller(比如 Deployment)可以设置为 Always 。

2、启动job

[root@ren7 yaml]# kubectl apply -f myjob.yaml 
job.batch/job created

3、查看job的状态

[root@ren7 yaml]# kubectl get job
NAME   COMPLETIONS   DURATION   AGE
job    1/1           3s         84s

4、查看pod的状态

[root@ren7 yaml]# kubectl get pod
NAME                                READY   STATUS        RESTARTS   AGE
job-m9shb                           0/1     Completed     0          2m40s

显示completed已经完成

5、查看pod的标准输出

[root@ren7 yaml]# kubectl logs job-m9shb
hello kubernetes

二、job失败的情况

如果job失败了会怎么样呢?

1、修改myjob.yaml文件,故意引入一个错误:

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EbeajtS8-1641264633463)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# cat myjob.yaml 
apiVersion:  batch/v1
kind: Job
metadata:
  name: job
spec:
  template:
     spec:
        containers:
            - name: job
              image: reg.yunwei.com/learn/busybox:latest
              command: ["echorrr","hello kubernetes"]
        restartPolicy: Never

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nVYsAixg-1641264633464)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

2、删除之前的job

[root@ren7 yaml]# kubectl delete -f myjob.yaml 
job.batch "job" deleted
[root@ren7 yaml]# kubectl get pod
No resources found.

3、运行新的job并查看状态

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3k8E89vd-1641264633466)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# kubectl apply -f myjob.yaml 
job.batch/job created
[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS               RESTARTS   AGE
job-l9spb   0/1     ContainerCannotRun   0          5s
job-mk5fp   0/1     ContainerCreating    0          1s
[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS               RESTARTS   AGE
job-2phbq   0/1     ContainerCreating    0          2s
job-l9spb   0/1     ContainerCannotRun   0          16s
job-mk5fp   0/1     ContainerCannotRun   0          12s

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9MxiDdvD-1641264633467)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

发现没有创建成功,显示0

并且可以看到有多个pod,状态均不正常。

4、使用 kubectldescribe pod 查看某个pod的启动日志

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ApOZEbZq-1641264633469)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# kubectl describe pods job-2phbq
Name:           job-2phbq
Namespace:      default
Node:           192.168.11.5/192.168.11.5
Start Time:     Fri, 25 Oct 2019 19:02:56 +0800
Labels:         controller-uid=f7746782-f716-11e9-867d-000c297d011c
                job-name=job
Annotations:    <none>
Status:         Failed
IP:             172.20.72.146
Controlled By:  Job/job
Containers:
  job:
    Container ID:  docker://858e1dffa45cad2e43fa096b002a925f15dfc07ad08b406c4c2ad01fe68c2ccd
    Image:         reg.yunwei.com/learn/busybox:latest
    Image ID:      docker-pullable://reg.yunwei.com/learn/busybox@sha256:dd97a3fe6d721c5cf03abac0f50e2848dc583f7c4e41bf39102ceb42edfd1808
    Port:          <none>
    Host Port:     <none>
    Command:
      echorrr
      hello kubernetes
    State:          Terminated
      Reason:       ContainerCannotRun
      Message:      OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"echorrr\": executable file not found in $PATH": unknown
      Exit Code:    127
      Started:      Fri, 25 Oct 2019 19:02:58 +0800
      Finished:     Fri, 25 Oct 2019 19:02:58 +0800
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-qvqql (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             False 
  ContainersReady   False 
  PodScheduled      True 
Volumes:
  default-token-qvqql:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-qvqql
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     <none>
Events:
  Type     Reason     Age   From                   Message
  ----     ------     ----  ----                   -------
  Normal   Scheduled  11m   default-scheduler      Successfully assigned default/job-2phbq to 192.168.11.5
  Normal   Pulling    11m   kubelet, 192.168.11.5  Pulling image "reg.yunwei.com/learn/busybox:latest"
  Normal   Pulled     11m   kubelet, 192.168.11.5  Successfully pulled image "reg.yunwei.com/learn/busybox:latest"
  Normal   Created    11m   kubelet, 192.168.11.5  Created container job
  Warning  Failed     11m   kubelet, 192.168.11.5  Error: failed to start container "job": Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"echorrr\": executable file not found in $PATH": unknown

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AlRF0NzQ-1641264633475)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

日志显示没有可执行程序符合我们的预期。

为什么kubectl get pod 会看到这么多个失败的pod?

原因是:当第一个 Pod 启动时,容器失败退出,根据 restartPolicy: Never,此失败容器不会被重启,但 Job DESIRED 的 Pod 是 1,目前 SUCCESSFUL 为 0,不满足,所以 Job controller 会启动新的 Pod,直到 SUCCESSFUL 为 1。对于我们这个例子,SUCCESSFUL 永远也到不了 1,所以 Job controller 会一直创建新的 Pod。为了终止这个行为,只能删除 Job。

[root@ren7 yaml]# kubectl delete -f myjob.yaml 
job.batch "job" deleted
[root@ren7 yaml]# kubectl get pod
No resources found.

如果将 restartPolicy 设置为 OnFailure 会怎么样?下面我们实践一下,修改 myjob.yml 后重新启动。

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kSPXTVUA-1641264633479)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# vim myjob.yaml     #依旧是错误命令,且改了restartPolicy: OnFailure
[root@ren7 yaml]# kubectl apply -f myjob.yaml 
job.batch/job created
[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS              RESTARTS   AGE
job-9fd6w   0/1     ContainerCreating   0          2s
[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS              RESTARTS   AGE
job-9fd6w   0/1     RunContainerError   0          14s
[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS              RESTARTS   AGE
job-9fd6w   0/1     RunContainerError   1          27s
[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS             RESTARTS   AGE
job-9fd6w   0/1     CrashLoopBackOff   2          36s

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n65yv5pr-1641264633482)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

完成依然为0。

这里只有一个 Pod,不过 RESTARTS 为 2,而且不断增加,说明 OnFailure 生效,容器失败后会自动重启。

三、并行执行job

有时,我们希望能同时运行多个pod,提高job的执行效率。

1、设置parallelism

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unEM0QkO-1641264633483)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# cat myjob.yaml 
apiVersion: batch/v1
kind: Job
metadata:
  name: job
spec:
  parallelism: 2
  template:
    spec:
      containers:
        - name: job
          image: reg.yunwei.com/learn/busybox:latest
      restartPolicy: Never

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b9q8W7Gb-1641264633484)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

2、执行该yaml文件

[root@ren7 yaml]# kubectl apply -f myjob.yaml 
job.batch/job created

3、查看job

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-anTlasNE-1641264633485)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS              RESTARTS   AGE
job-5jkpz   0/1     ContainerCreating   0          3s
job-svs94   0/1     ContainerCreating   0          3s
[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS      RESTARTS   AGE
job-5jkpz   0/1     Completed   0          10s
job-svs94   0/1     Completed   0          10s

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O1q7Un65-1641264633492)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

job一共启动了两个pod,而且AGE相同,可见是并行运行的。

4、还可以通过 completions 设置 Job 成功完成 Pod 的总数:

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-89EHnq5J-1641264633494)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# cat myjob.yaml 
apiVersion: batch/v1
kind: Job
metadata:
  name: job
spec:
  parallelism: 2
  completions: 6
  template:
    spec:
      containers:
        - name: job
          image: reg.yunwei.com/learn/busybox:latest
      restartPolicy: Never

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XvkB8a6m-1641264633496)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

5、查看相应的pod和job

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9nanK2JQ-1641264633497)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# kubectl get pod
NAME        READY   STATUS      RESTARTS   AGE
job-82gll   0/1     Completed   0          18s
job-gsn55   0/1     Completed   0          18s
job-h6gnw   0/1     Completed   0          11s
job-nz5vs   0/1     Completed   0          14s
job-v48cr   0/1     Completed   0          15s
job-vx5gt   0/1     Completed   0          10s
[root@ren7 yaml]# kubectl get job
NAME   COMPLETIONS   DURATION   AGE
job    6/6           11s        72s

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F8tgvzNy-1641264633499)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

如果不指定 completions 和 parallelism,默认值均为 1。

上面的例子只是为了演示 Job 的并行特性,实际用途不大。不过现实中确实存在很多需要并行处理的场景。比如批处理程序,每个副本(Pod)都会从任务池中读取任务并执行,副本越多,执行时间就越短,效率就越高。这种类似的场景都可以用 Job 来实现。

四、定时执行job

Linux 中有 cron 程序定时执行任务,Kubernetes 的 CronJob 提供了类似的功能,可以定时执行 Job。

1、CronJob 配置文件示例如下:

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uXbERoyu-1641264633500)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

[root@ren7 yaml]# cat myjob1.yaml 
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: timing
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
         spec:
           containers:
             - name: timing
               image: reg.yunwei.com/learn/busybox:latest
               command: ["echo","hello k8s cronjob!"]
           restartPolicy: OnFailure

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iYsARwSw-1641264633508)(K8s学习.assets/copycode-16412272730031.gif)]](javascript:void(0)😉

① batch/v1beta1 是当前 CronJob 的 apiVersion。

② 指明当前资源的类型为 CronJob。

③ schedule 指定什么时候运行 Job,其格式与 Linux cron 一致。这里 */1 * * * * 的含义是每一分钟启动一次。

④ jobTemplate 定义 Job 的模板,格式与前面 Job 一致。

2、通过 kubectl apply 创建 CronJob

[root@ren7 yaml]# kubectl apply -f myjob1.yaml 
cronjob.batch/timing created

3、查看crontab的状态

[root@ren7 yaml]# kubectl get job
No resources found.
[root@ren7 yaml]# kubectl get cronjob
NAME     SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
timing   */1 * * * *   False     0        <none>          15s

4、等待几分钟再次查看jobs的执行情况

[root@ren7 yaml]# kubectl get job
NAME                COMPLETIONS   DURATION   AGE
timing-1572005160   1/1           3s         2m29s
timing-1572005220   1/1           3s         89s
timing-1572005280   1/1           3s         29s

可以看到每隔一分钟就会启动一个job。

过段时间查看pod

[root@ren7 yaml]# kubectl get pod
NAME                      READY   STATUS      RESTARTS   AGE
timing-1572005340-5fds8   0/1     Completed   0          2m40s
timing-1572005400-8qsd4   0/1     Completed   0          99s
timing-1572005460-hnsh7   0/1     Completed   0          39s

5、执行kubectl logs 可查看某个 Job 的pod运行日志:

[root@ren7 yaml]# kubectl logs timing-1572005340-5fds8
hello k8s cronjob!

查看pod会遗留很多已经完成的pod,只需要删除即可。

[root@ren7 yaml]# kubectl delete -f myjob1.yaml 
cronjob.batch "timing" deleted
[root@ren7 yaml]# kubectl get pods
No resources found.

2、k8s之Secret

Secret详解

secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。
 
 用户可以创建自己的secret,系统也会有自己的secret。
 Pod需要先引用才能使用某个secret

Pod有2种方式来使用secret:

1. 作为volume的一个域被一个或多个容器挂载
2. 在拉取镜像的时候被kubelet引用。

內建的Secrets:

由ServiceAccount创建的API证书附加的秘钥k8s自动生成的用来访问apiserver的Secret,所有Pod会默认使用这个Secret与apiserver通信

创建自己的Secret:

方式1:使用kubectl create secret命令
方式2:yaml文件创建Secret

命令方式创建secret:

假如某个Pod要访问数据库,需要用户名密码,分别存放在2个文件中:username.txt,password.txt

例子:

[root@kub-k8s-master ~]# echo -n 'admin' > ./username.txt
[root@kub-k8s-master ~]# echo -n '1f2d1e2e67df' > ./password.txt

kubectl create secret指令将用户名密码写到secret中,并在apiserver创建Secret

[root@kub-k8s-master ~]# kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret/db-user-pass created

查看创建结果:

[root@kub-k8s-master ~]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
db-user-pass          Opaque                                2      54s
default-token-6svwp   kubernetes.io/service-account-token   3      4d11h

注: opaque:英[əʊˈpeɪk] 美[oʊˈpeɪk]  模糊

查看详细信息:

[root@kub-k8s-master ~]# kubectl describe secrets/db-user-pass
Name:         db-user-pass
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password.txt:  12 bytes
username.txt:  5 bytes 

get或describe指令都不会展示secret的实际内容,这是出于对数据的保护的考虑,如果想查看实际内容使用命令:

[root@kub-k8s-master ~]# kubectl get secret db-user-pass -o json

base64解码:

[root@kub-k8s-master ~]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1f2d1e2e67df

yaml方式创建Secret:

创建一个secret.yaml文件,内容用base64编码:明文显示容易被别人发现,这里先转码。
[root@kub-k8s-master ~]# echo -n 'admin' | base64
YWRtaW4=
[root@kub-k8s-master ~]# echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm

创建一个secret.yaml文件,内容用base64编码

[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque  #模糊
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

创建:

[root@kub-k8s-master prome]# kubectl apply -f secret.yml 
secret/mysecret created

解析Secret中内容,还是经过编码的—需要解码

[root@kub-k8s-master ~]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-7vc82   kubernetes.io/service-account-token   3      30h
mysecret              Opaque                                2      6s

[root@kub-k8s-master prome]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2019-10-21T03:07:56Z"
  name: mysecret
  namespace: default
  resourceVersion: "162855"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: 36bcd07d-92eb-4755-ac0a-a5843ed986dd
type: Opaque

使用Secret

一个Pod中引用Secret的列子:

[root@kub-k8s-master prome]# vim pod_use_secret.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: testredis
    image: daocloud.io/library/redis
    volumeMounts:    #挂载一个卷
    - name: foo     #这个名字需要与定义的卷的名字一致
      mountPath: "/etc/foo"  #挂载到容器里哪个目录下,随便写
      readOnly: true
  volumes:     #数据卷的定义
  - name: foo   #卷的名字这个名字自定义
    secret:    #卷是直接使用的secret。
      secretName: mysecret   #调用刚才定义的secret
      
创建:
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/
root@mypod:/etc/foo# ls
password  username
root@mypod:/etc/foo# cat password 
1f2d1e2e67df
每一个被引用的Secret都要在spec.volumes中定义
 如果Pod中的多个容器都要引用这个Secret那么每一个容器定义中都要指定自己的volumeMounts,但是Pod定义中声明一次spec.volumes就好了。 

映射secret key到指定的路径

[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml 
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: testredis
    image: daocloud.io/library/redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:   #定义一个items
       - key: username   #将那个key重新定义到那个目录下
         path: my-group/my-username  #相对路径,相对于/etc/foo的路径
        
2.创建
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
3.从volume中读取secret的值
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash                         
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username 
admin
root@mypod:/etc/foo/my-group#

username被映射到了文件/etc/foo/my-group/my-username而不是/etc/foo/username

被挂载的secret内容自动更新

也就是如果修改一个Secret的内容,那么挂载了该Secret的容器中也将会取到更新后的值,但是这个时间间隔是由kubelet的同步时间决定的。

1.设置base64加密
[root@kub-k8s-master prome]# echo qianfeng | base64
cWlhbmZlbmcK
2.将admin替换成qianfeng
[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: cWlhbmZlbmcK   #修改为qianfeng的base64加密后的
  password: MWYyZDFlMmU2N2Rm
  
1.创建
[root@kub-k8s-master prome]# kubectl apply -f secret.yml 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
secret/mysecret configured
2.连接pod容器
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username 
qianfeng

以环境变量的形式使用Secret

[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml 
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: testredis
    image: daocloud.io/library/redis
    env:  #定义环境变量
     - name: SECRET_USERNAME   #创建新的环境变量名称
       valueFrom:
        secretKeyRef:     #调用的key是什么
         name: mysecret       #变量的值来自于mysecret
         key: username       #username里面的值

2.创建使用secret的pod容器
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
3.连接
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash 
root@mypod:/data# echo $SECRET_USERNAME   #打印一下定义的变量
qianfeng 

实验

方法1. 使用 kubectl create secret 指令创建Secret对象

[root@kub-k8s-master ~]# vim user.txt
admin
[root@kub-k8s-master ~]# vim passwd.txt
c1oudc0w!

创建secret

[root@kub-k8s-master ~]#  kubectl create secret generic user --from-file=user.txt
secret/user created
[root@kub-k8s-master ~]#  kubectl create secret generic pass --from-file=passwd.txt
secret/pass created

user.txt 和 passwd.txt 文件里,存放的就是用户名和密码;而 user 和 pass,则是为 Secret 对象指定的名字。

查看Secret 对象:

[root@kub-k8s-master ~]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
pass                  Opaque                                1      56s
user                  Opaque                                1      71s

方法2. 通过编写 YAML 文件的方式来创建这个 Secret 对象

Secret 对象要求这些数据必须是经过 Base64 转码的,以免出现明文密码的安全隐患。

转码操作:

[root@kub-k8s-master ~]# echo -n 'admin' | base64
YWRtaW4=
[root@kub-k8s-master ~]# echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm

注意:像这样创建的 Secret 对象,它里面的内容仅仅是经过了转码,并没有被加密。生产环境中,需要在 Kubernetes 中开启 Secret 的加密插件,增强数据的安全性。

[root@kub-k8s-master prome]# vim create_secret.yml
---
apiVersion: v1
kind: Secret
metadata:
  name: mysecret-01
type: Opaque
data:
  user: YWRtaW4=
  pass: MWYyZDFlMmU2N2Rm
  
[root@kub-k8s-master prome]# kubectl apply -f create_secret.yml 
secret/mysecret-01 created

[root@kub-k8s-master prome~]# kubectl get secret

用yaml方式创建的secret调用方法如下:

[root@kub-k8s-master prome]# vim test-projected-volume.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: test-projected-volume
spec:
  containers:
  - name: test-secret-volume
    image: daocloud.io/library/nginx
    volumeMounts:
    - name: mysql-cred
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: mysql-cred
    secret:
      secretName: mysecret-01

创建这个 Pod:

[root@kub-k8s-master prome]# kubectl apply -f test-projected-volume.yaml 
pod/test-projected-volume1 created

验证这些 Secret 对象是不是已经在容器里了:

[root@kub-k8s-master prome]# kubectl exec -it test-projected-volume  /bin/bash
root@test-projected-volume:/# ls
bin   dev  home  lib64  mnt  proc          root  sbin  sys  usr
boot  etc  lib   media  opt  projected-volume  run   srv   tmp  var
root@test-projected-volume:/# ls projected-volume/
pass  user
root@test-projected-volume:/# cat projected-volume/pass 
1f2d1e2e67df
root@test-projected-volume:/# cat projected-volume/user 
admin
root@test-projected-volume:/#

注意:

如果报错:上面这条命令会报错如下
# kubectl exec -it test-projected-volume /bin/sh
error: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)

 

解决:绑定一个cluster-admin的权限
# kubectl create clusterrolebinding system:anonymous   --clusterrole=cluster-admin   --user=system:anonymous
clusterrolebinding.rbac.authorization.k8s.io/system:anonymous created

结果中看到,保存在 Etcd 里的用户名和密码信息,已经以文件的形式出现在了容器的 Volume 目录里。

而这个文件的名字,就是 kubectl create secret 指定的 Key,或者说是 Secret 对象的 data 字段指定的 Key。

总结问题:

1、ngnix启动一直处于创建中

1、查看报错日志

kubectl describe pod nginx-86c57db685-gfxzp

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MRpx8iHn-1641264633511)(K8s学习.assets/image-20211227013132293.png)]

2、去对应节点查看日志

journalctl -u kubelet -n 1000

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cFxn8ijD-1641264633514)(K8s学习.assets/image-20211227013213737.png)]

3、补救措施

[Kubernetes]node节点pod无法启动/节点删除网络重置
node1之前反复添加过,添加之前需要清除下网络

root@master1:/var/lib/kubelet# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-8586cf59-6zw9k 1/1 Running 0 9m 10.244.3.3 node2
nginx-8586cf59-jk5pc 0/1 ContainerCreating 0 9m node1
nginx-8586cf59-vm9h4 0/1 ContainerCreating 0 9m node1
nginx-8586cf59-zjb84 1/1 Running 0 9m 10.244.3.2 node2
root@node1:~# journalctl -u kubelet
failed: rpc error: code = Unknown desc = NetworkPlugin cni failed to set up pod “nginx-8586cf59-rm4sh_default” network: failed to set bridge addr: “cni0” already has an IP address different from 10.244.2.1/24
12252 cni.go:227] Error while adding to cni network: failed to set bridge addr: “cni0” already
排查节点日志:journalctl -u kubelet

重置kubernetes服务,重置网络。删除网络配置,link

kubeadm reset
systemctl stop kubelet
systemctl stop docker
rm -rf /var/lib/cni/
rm -rf /var/lib/kubelet/*
rm -rf /etc/cni/
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig docker0 down
ip link delete cni0
ip link delete flannel.1
systemctl start docker

获取master的join token

kubeadm token create --print-join-command
加入节点

kubeadm join --token 55c2c6.2a4bde1bc73a6562 192.168.1.144:6443 --discovery-token-ca-cert-hash sha256:0fdf8cfc6fecc18fded386

kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous

clusterrolebinding.rbac.authorization.k8s.io/system:anonymous created


结果中看到,保存在 Etcd 里的用户名和密码信息,已经以文件的形式出现在了容器的 Volume 目录里。

而这个文件的名字,就是 kubectl create secret 指定的 Key,或者说是 Secret 对象的 data 字段指定的 Key。

# 总结问题:

## 1、ngnix启动一直处于创建中

1、查看报错日志

kubectl describe pod  nginx-86c57db685-gfxzp

[外链图片转存中...(img-MRpx8iHn-1641264633511)]

2、去对应节点查看日志

journalctl -u kubelet -n 1000

[外链图片转存中...(img-cFxn8ijD-1641264633514)]

3、补救措施

[Kubernetes]node节点pod无法启动/节点删除网络重置
node1之前反复添加过,添加之前需要清除下网络

root@master1:/var/lib/kubelet# kubectl get pod -o wide
NAME                   READY     STATUS              RESTARTS   AGE       IP           NODE
nginx-8586cf59-6zw9k   1/1       Running             0          9m        10.244.3.3   node2
nginx-8586cf59-jk5pc   0/1       ContainerCreating   0          9m        <none>       node1
nginx-8586cf59-vm9h4   0/1       ContainerCreating   0          9m        <none>       node1
nginx-8586cf59-zjb84   1/1       Running             0          9m        10.244.3.2   node2
root@node1:~# journalctl -u kubelet
 failed: rpc error: code = Unknown desc = NetworkPlugin cni failed to set up pod "nginx-8586cf59-rm4sh_default" network: failed to set bridge addr: "cni0" already has an IP address different from 10.244.2.1/24
12252 cni.go:227] Error while adding to cni network: failed to set bridge addr: "cni0" already
排查节点日志:journalctl  -u kubelet

重置kubernetes服务,重置网络。删除网络配置,link

kubeadm reset
systemctl stop kubelet
systemctl stop docker
rm -rf /var/lib/cni/
rm -rf /var/lib/kubelet/*
rm -rf /etc/cni/
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig docker0 down
ip link delete cni0
ip link delete flannel.1
systemctl start docker

获取master的join token

kubeadm token create --print-join-command
加入节点

kubeadm join --token 55c2c6.2a4bde1bc73a6562 192.168.1.144:6443 --discovery-token-ca-cert-hash sha256:0fdf8cfc6fecc18fded386



  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 在 Kubernetes 中部署服务通常需要以下步骤: 1. 准备你的应用程序的源代码和必要的依赖项,并构建成 Docker 镜像。 2. 创建 Kubernetes 部署描述文件,其中包含有关如何在集群中运行你的应用程序的信息。 3. 使用 kubectl 命令将部署描述文件提交到集群。Kubernetes 将自动根据描述文件创建所需的容器、服务和其他资源。 4. 通过监视 Kubernetes 集群的状态来确保应用程序正常运行。 你可以使用命令行工具或 Kubernetes 管理平台(如 Dashboard)来执行上述步骤。如果你是初学者,可以使用 Kubernetes 在本地运行的工具(如 Minikube)来更轻松地开始学习。 ### 回答2: Kubernetes(简称为k8s)是一个广泛使用的容器编排平台,可以帮助我们高效地部署和管理微服务。 首先,我们需要将每个微服务打包成容器镜像,例如Docker镜像。这样可以确保每个微服务都是独立的、可移植的,并且可以在任何地方运行。 接下来,我们需要创建一个Kubernetes集群以托管我们的微服务。一个Kubernetes集群由多个主机节点组成,每个节点上运行着一个或多个Kubernetes控制组件和工作负载副本。 在集群中,我们需要定义一个叫做"Pods"的抽象,一个Pod可以包含一个或多个相关的容器。每个Pod都有自己的IP地址和存储资源,这样可以确保微服务之间的隔离性。 接下来,我们需要定义一个叫做"Deployment"的Kubernetes资源,用于描述我们的微服务的期望状态。Deployment通过定义副本数量、容器镜像和其他配置来定义微服务部署。 除此之外,我们还可以使用"Service"来定义我们的微服务的网络访问方式。Service可以将一组Pods封装在一个虚拟IP地址后面,以提供负载均衡和服务发现功能。 另外,我们还可以使用"ConfigMap"和"Secret"来管理我们微服务的配置信息和敏感信息,例如数据库连接字符串、API密钥等。 最后,我们可以使用Kubectl命令行工具或编写YAML文件来提交我们的Kubernetes资源定义,Kubernetes会根据这些定义进行相应的操作以部署和管理我们的微服务总结起来,k8s可以通过将微服务打包成容器镜像,并利用Kubernetes的抽象和资源管理能力来高效地部署和管理微服务。它提供了一种可伸缩、弹性、高可用的部署方式,能够帮助我们更好地实现微服务架构。 ### 回答3: Kubernetes(简称K8s)是一个用于自动化部署、扩展和管理容器化应用程序的开源平台。部署服务在K8s中涉及以下步骤: 1. 创建K8s集群:首先,需要在物理或虚拟机上创建一个K8s集群。集群由多个节点组成,其中包括主控节点(Master)和工作节点(Worker)。 2. 定义Docker镜像:使用Docker将每个微服务打包为容器。每个微服务应该有自己的Dockerfile,其中包含构建镜像所需的指令。 3. 编写K8s配置文件:创建一个YAML或JSON格式的K8s配置文件,用于描述应用程序的部署需求。该文件包括容器镜像的名称、端口映射、资源需求等信息。 4. 部署Deployment:使用K8s的Deployment资源部署服务。Deployment定义了在集群中如何运行应用程序,并能够根据需要进行自动扩展。 5. 服务暴露:在K8s中,可以通过使用Service资源来为微服务创建一个稳定的网络终点。Service可以将入口流量负载均衡到后端运行着微服务的Pod。 6. 监控与日志:K8s提供了一些内置的监控和日志记录功能,可以用于观察应用程序的运行状态和性能指标。可以使用Prometheus等工具进行监控,使用ELK(Elasticsearch+Logstash+Kibana)堆栈进行日志管理。 7. 进行扩展:使用K8s的伸缩功能可以根据需求动态调整微服务的副本数量。可以手动或使用自动扩展机制来增加或减少Pod的数量。 8. 持续集成与持续部署:将微服务部署至K8s集群的过程可以与持续集成和持续部署(CI/CD)流程集成。通过使用工具如Jenkins,可以实现自动构建、测试和部署服务。 通过以上步骤,可以在K8s中成功部署服务。K8s提供了许多功能和工具,可以帮助管理和扩展容器化应用程序,并提供高可用性和可伸缩性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值