1 简单使用Pod

Pod是k8s的基本单位。一个pod可以由一个或多个关系紧密的容器构成。

1.1 创建Pod

(1)创建模板文件”myalpinepod.yaml“

# myalpinepod.yaml
# 注意键值对中的“空格”

# 使用v1版本的API
apiVersion: v1

# 设置创建的资源对象
kind: Pod

# 设置该资源对象的元数据
metadata: 
  # 设置资源对象的名称
  name: myalpinepod
  # 设置资源对象标签
  labels:
    app: myalpinepodlabel

# 设置资源对象的详细数据
spec:
  # 配置容器
  containers:
    # 容器名称
    - name: myalpinepod-container
      # 配置镜像
      image: alpine:3.12
      # 配置镜像下载策略,ifNotPresent表示只有镜像不存在时,才会拉取
      imagePullPolicy: IfNotPresent
      # 容器启动的参数
      command: ["/bin/sh","-c","--"]
      args: ["while true; do sleep 30; done;"]

  # 设置重启策略,Never表示不再重启该pod
  # 注意:k8s中不支持重启、停止、启动Pod资源,只有删除重建
  # 因为Pod是一个运行服务的实例,随时有可能在一个Node上停止,在另一个Node重建
  restartPolicy: Never

(2)执行模板文件,生成Pod

kubectl apply -f myalpinepod.yaml

1.2 查看Pod

# 查看Pod
# -A: 显示所有Pod
kubectl get pod

NAME          READY   STATUS      RESTARTS   AGE
myalpinepod   0/1     Running   0          5s

# 查看Pod的更多概要信息
# -o json: 表示以json方式查看Pod详细信息
# -o yaml: 表示以yaml方式查看Pod详细信息
kubectl get pod -o wide

# 实时监控Pod
kubectl get pod -w

# 查看myalpinepod的详细信息
kubectl describe pods myalpinepod

# 查看myalpinepod的日志
kubectl logs myalpinepod

1.3 删除Pod

# 基于Pod删除
kubectl delete pod myalpinepod

# 基于模板文件删除
kubectl delete -f myalpinepod.yaml

# 当修改完yaml文件后,可以使用replace更新Pod
kubectl replace -f myalpinepod.yaml --force

1.4 进入Pod

# 查看Pod中的容器
kubectl get pods myalpinepod -o jsonpath={.spec.initContainers[*].name}

# 进入指定容器执行命令:
# kubectl exec -it <pod-name>  -- /bin/bash
# 注意也有可能是 /bin/sh
# kubectl exec -it <pod-name>  -- /bin/sh
kubectl exec -it myalpinepod /bin/sh

1.5 Pod模板

查看Pod模板配置

kubectl explain pod

详细配置如下:

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

1.6 常见Pod的状态

相位值(或状态)

说明

Pending

Pod创建成功

Running

Pod已绑定到Node,容器创建成功,至少有一个容器还在运行

Succeeded

Pod中全部容器已成功终止

Failed

Pod中全部容器已终止,但至少有一个容器表现出失败终止状态

Completed

Pod内容器创建成功,但容器启动失败

CrashLoopBackOff

容器退出,kubelet正在将它重启

ContainerCreating

容器创建中

RunContainerError

启动容器失败

InvalidImageName

无法解析镜像名称

CreateContainerError

创建容器失败

2 简单使用控制器

2.1 k8s中的控制器

一般情况下,用户不需要直接创建Pod,而是直接创建控制器,由控制器直接管理Pod。

控制器

Deployment

适合无状态的服务部署,用来创建Pod和ReplicaSet滚动更新和回滚扩容和缩容暂停与恢复

DaemonSet

在集群中的各个Node上运行且仅运行一个副本

Job

基于某一特定任务而运行,当运行任务的容器完成工作后,就成功退出

ConJob

它是在Job的基础上添加了时间调度,可以在设定的时间运行任务,也可以定期运行任务

StatefulSet

适合有状态的服务部署,它是一种提供排序和唯一性保证的特殊Pod控制器

ReplicaSet

保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级

2.2 创建Deployment控制器

Deployment的功能支持ReplicaSet 的所有功能,支持发布的停止、继续,支持版本的滚动更新和回退功能。

(1)创建模板文件”nginxDeployment.yaml“

# nginxDeployment.yaml
# 选择版本号,apps/v1表示K8s API的稳定版
apiVersion: apps/v1

# 设置创建的资源对象
kind: Deployment

# 设置该资源对象的信息
metadata:
  # 资源名称
  name: nginxdeployment
  # 设置资源的命名空间,可以不设置默认是“default”
  # namespace: dev

# 设置资源对象的元数据
spec:
  # 设置选择器,可以建立控制器和Pod之间的关系,控制器可使用标签管理Pod
  selector:
    # 设置自定义标签
    matchLabels:
      app: nginx-pod
  
  # 设置控制器托管的Pod需要保持的副本数量
  replicas: 3

  # 设置Pod模板,当副本数量不足时,会根据下面的模板创建pod副本
  template:
    metadata:
      labels:
        # 此处必须要与上面的matchLabels相同
        app: nginx-pod

    spec:
      containers:
        - name: containernginx
          image: nginx:1.20.0
          imagePullPolicy: IfNotPresent
          ports:
            - name: portnginx
              containerPort: 80

(2)执行模板文件,生成Deployment

# --record:在执行模板时,建议添加,它可以把每次修改Deployment控制器时使用的命令记录到备注字段中,便于后期维护控制器
kubectl apply -f myalpinepod.yaml --record

2.3 查看控制器

# 查看控制器
kubectl get deployment

# 查看控制器的概要信息
kubectl get deployment -o wide

# 实时监控Deployment
kubectl get deployment -w

# 查看nginxdeployment的详细信息
kubectl describe deployment nginxdeployment

2.4 删除控制器

kubectl delete deployment nginxdeployment

2.5 Deployment模板

# 必选,接口版本
apiVersion: apps/v1
# 必选,资源类型
kind: Deployment             
# 元数据
metadata:
  # 必选,控制器名称
  name: String
  # 控制器命名空间
  namespace: String
  # 自定义标签列表
  labels:
    key: value
spec:
  # 设置选择器,可以建立控制器和Pod之间的关系,控制器可使用标签管理Pod
  selector:
    # 设置自定义标签
    matchLabels:
      key: value
  # 设置Pod数量
  replicas: int
  # 设置Pod的更新策略
  strategy:
    # Recreate:先终止所有已存在的Pod,再创建出新的Pod
    # RollingUpdate:滚动更新,终止一部分Pod,同时启动一部分Pod,在更新过程中,存在两个版本Pod
    type: Recreate/RollingUpdate
    rollingUpdate:
      # 滚动更新时,在所需数量的Pod上,允许创建的最大Pod数量
      maxSurge: int/int%
      # 滚动更新时,同时存在最大不可用Pod数量
      maxUnavailable: int/int%
  # 必填,Pod的模板,参见Pod模板
  template: [PodTemplate]

3 简单使用Service

Service是K8s内部服务注册与负载均衡的一种组件,对相同功能的Pod进行逻辑分组,实现使用唯一的地址访问资源和服务。Service可用于将K8s集群内部服务发布出去(向外发布),也可用于将外部服务引入进来或者仅对内部提供服务(向内发布)。Service向外发布的服务类型有ClusterIP(默认方式)、NodePort和LoadBalancer,向内发布的服务类型有HeadLinesss、ExternalName。此处,简单使用一下ClusterIP类型。

3.1 创建Deployment控制器

Deployment控制器提供Service向外发布服务。

(1)创建“python-deployment-for-service.yaml”Deployment模板

# python-deployment-for-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-deployment-for-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: python-for-service-pod
  template:
    metadata:
      labels:
        app: python-for-service-pod
    spec:
      containers:
        - name: python-sevice
          image: python:3.8.2
          imagePullPolicy: IfNotPresent
          command: ['/bin/bash', '-c', '--']
          # 启动"python -m http.server 80"服务
          args: ['echo "<p> The host is $(hostname) </p>" > index.html; python -m http.server 80']
          # 设置80端口
          ports:
            - name: http
              containerPort: 80

(2)执行模板文件

# 执行控制器
kubectl apply -f python-deployment-for-service.yaml --record

(3)查看控制器

# 查看控制器详细信息
kubectl get deployment -o wide

# 查看Pod
kubectl get pod -o wide

# Pod的详细信息如下:
NAME                                             READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
python-deployment-for-service-5f54648c46-ccssn   1/1     Running   1          51m   10.12.1.20   mason-node2   <none>           <none>
python-deployment-for-service-5f54648c46-gc8w2   1/1     Running   1          51m   10.12.1.21   mason-node2   <none>           <none>
python-deployment-for-service-5f54648c46-gztgw   1/1     Running   1          51m   10.12.1.22   mason-node2   <none>           <none>

# 查看Pod服务
kubectl get pod -o wide

# 查看单个pod提供的服务
curl 10.12.1.20
# 返回值信息如下
<p> The host is python-deployment-for-service-5f54648c46-ccssn </p>

(4)出现Pod节点无法ping通

可以在每个子节点中执行以下命令

# iptables是Linux平台下包过滤防火墙,注意Ubuntu下需要添加sudo
# Centos下
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -L -n

# ubuntu下
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables -L -n

3.2 创建Service服务

3.2.1 创建ClusterIP类型

(1)创建“python-clusterip-service.yaml”模板

# python-clusterip-service.yaml
apiVersion: v1
# 服务资源
kind: Service
# 元数据
metadata:
  # 服务名称
  name: python-clusterip-service
spec:
  # 标签选择器
  selector:
    # 注意:此处一定要与python-deployment-for-service.yaml中的labels对应
    app: python-for-service-pod
  # Service类型
  type: ClusterIP
  # 设置端口
  ports:
    # 设置协议
    - protocol: TCP
      # Service端口
      port: 8080
      # 应用端口(Pod端口)
      targetPort: 80

(2)执行模板

kubectl apply -f python-clusterip-service.yaml

(3)查看执行结果

# 内部查看,“10.11.62.32”是python-clusterip-service的IP
curl 10.11.62.32:8080
# 返回值
<p> The host is python-deployment-for-service-bfb9ccbfb-7b48d </p>

3.2.2 创建NodePort类型

(1)创建“python-nodeport-service.yaml”模板

# python-nodeport-service.yaml
apiVersion: v1
# 服务资源
kind: Service
# 元数据
metadata:
  # 服务名称
  name: python-nodeport-service
spec:
  # 标签选择器
  selector:
    # 注意:此处一定要与python-deployment-for-service.yaml中的labels对应
    app: python-for-service-pod
  # Service类型
  type: NodePort
  # 设置端口
  ports:
    # 设置协议
    - protocol: TCP
      # Service端口
      port: 8080
      # 应用端口(Pod端口)
      targetPort: 80
      # 映射到主机的端口
      nodePort: 30001

(2)执行模板

kubectl apply -f python-nodeport-service.yaml

(3)查看效果

# 内部查看,“10.11.240.208”是python-nodeport-service的IP
curl 10.11.240.208:8080
# 返回值
<p> The host is python-deployment-for-service-bfb9ccbfb-h4j2t </p>

# 使用节点查看,“192.168.108.100”是Master节点的IP
curl 192.168.108.100:30001
# 返回值
<p> The host is python-deployment-for-service-bfb9ccbfb-9wgms </p>

在浏览器中查看

k8s取代openstack k8s openapi_Pod

3.3 查看Service

# 可以将service换成svc

# 查看Service
kubectl get service -o wide
# 详细信息如下
NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes                 ClusterIP   10.11.0.1       <none>        443/TCP          2d
python-clusterip-service   ClusterIP   10.11.62.32     <none>        8080/TCP         3s
python-nodeport-service    NodePort    10.11.240.208   <none>        8080:30001/TCP   12m

# 查看Service的详细信息
kubectl describe service python-clusterip-service

3.4 删除Service

# 删除clusterIP服务
kubectl delete service python-clusterip-service

# 删除NodePort服务
kubectl delete service python-nodeport-service

3.5 Service模板

# 版本
apiVersion: v1
# 服务资源
kind: Service
# 元数据
metadata:
  # 服务名称
  name: String
  # Service所属的命名空间
  namespace: String
  # Service标签
  labels:
    - name: String
  # Service注解
  annotations:
    - name: String
spec:
  # 注意:标签选择器,键值对,管理指定标签的Pod,对应控制器中的labels,非常重要
  selector: []
  # Service类型, ClusterIP、NodePort、LoadBalancer、ExternalName
  type: String
  # 设置端口
  ports:
    # 端口名称
    - name: String
      # 设置协议
      protocol: TCP
      # Service端口
      port: int
      # 应用端口(Pod端口)
      targetPort: int
      # 当spec.type=NodePort时,设置映射到主机的端口,端口范围是30000~32767
      nodePort: int
  # 当spec.type=LoadBalancer时,设置外部负载均衡的地址
  status:
    loadBalancer:
      ingress:
        # 外部负载均衡的IP地址
        ip: String
        # 外部负载均衡的主机名
        hostname: String