通用

1
2
k get ns # 查看namespace列表
k api-resources # 查看对象列表,及对应的短名,是否属于namespace,kind等
1
k get ns default -v 9

使用-v 9指定日志详细程度

1
k get pods -oyaml -w
  • -oyaml 以yaml格式查看
  • -owide 以表格格式查看
  • -w watch后续的变化
1
k describe pod nginx

describe展示资源的详细信息和相关Event,常用于查看pod的历史状态。

1
k exec -it nginx-deployment -- bash

exec提供进入容器的通道,即使目标容器不在当前机器上。kubectl本质上还是发送HTTP请求。 使用--分割kubectl命令和进入容器后要执行的命令。 -it交互式执行。

1
k logs {POD_NAME}

查看pod的标准输出(stdout, stderr),与tail用法类似。

1
kubectl create serviceaccount ingress-controller-sa --dry-run=client -oyaml > manifests/ingress-controller-sa.yaml

指定--dry-run=client -oyaml仅打印API的定义,不会执行创建操作。

1
kubectl set resources deployment nginx-app -c=nginx -limits=cpu=500m,memory=128Mi

限制deployment nginx-app下容器名为nginx的容器最多使用50%的CPU和128MB的内存。

1
2
docker inspect -f {{.State.Pid}} $cid
nsenter -t $pid -n ifconfig # $pid 容器在主机上的pid, -n 进入网络namespace

通过nsenter进入容器namespace,执行主机上的命令。常用于容器内没有调试工具的情况。

对象使用

通过对象组合完成业务描述

  • 引用依赖:ingress->service, pod->node
  • 基于标签:replicaset->pod, service->pod
  • 基于命名:deployment->replicaset

每个API对象都有四大属性:

  • TypeMeta
    • gkv
  • MetaData
    • namespace/name/labels/annotations/finalizer/resourceVersion
  • Spec
  • Status

kubectl create XX –dry-run=client -o yaml 可以仅生成资源的yaml定义而不创建资源

Pod

带有健康检查探针的Pod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: centos
  name: centos
spec:
  replicas: 1
  selector:
    matchLabels:
      run: centos
  template:
    metadata:
      labels:
        run: centos
    spec:
      containers:
      - command:
        - tail
        - -f
        - /dev/null
        image: centos
        name: centos
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 5
          periodSeconds: 5

ConfigMap

示例

1
2
3
4
$ kubectl create configmap envoy-config --from-file=envoy.yaml
$ kubectl create -f envoy-deploy.yaml
# envoy启动时读取 /etc/envoy/envoy.yaml 文件
$ kubectl expose deploy envoy --selector run=envoy --port=10000 --type=NodePort
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: envoy
  name: envoy
spec:
  replicas: 1
  selector:
    matchLabels:
      run: envoy
  template:
    metadata:
      labels:
        run: envoy
    spec:
      containers:
      - image: envoyproxy/envoy:v1.19.0
        name: envoy
        volumeMounts:
        - name: envoy-config
          mountPath: "/etc/envoy"
          readOnly: true
      volumes:
      - name: envoy-config
        configMap:
          name: envoy-config

将properties文件内容加载到configMap

1
2
3
4
# 两种方式
kubectl create configmap game-config --from-file=game.properties
kubectl create configmap game-env-config --from-env-file=game.properties
kubectl get configmap -oyaml game-config

将字面量保存到configMap

1
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

设置到环境变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Pod
metadata:
  name: downward-api-pod
spec:
  containers:
    - name: test-container
      image: nginx
      command: [ "/bin/sh", "-c", "env" ]
      env:
        # Define the environment variable
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              # The ConfigMap containing the value you want to assign to SPECIAL_LEVEL_KEY
              name: special-config
              # Specify the key associated with the value
              key: special.how
  restartPolicy: Never

设置到文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "ls /etc/config/" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

Secret

UserAccount/Serviceaccont

  • 用户帐户是跨namespace的
  • 机机帐户是namespace相关的

Service

  • 通过labels为应用提供负载均衡和服务发现
  • kube-proxy负责具体实施,iptables/ipvs

Replica Set

Deployment

Statefulset

有状态副本集:

  • 每个Pod挂在自己独立的存储,如果一个Pod故障,从其它Node启动一个同名Pod,将原来的存储挂在新的Pod上
  • 适用于数据库等有状态服务
  • 每个Pod名字结尾是固定的编号,每个Pod都有自己的身份
    • Replicaset的Pod结尾是随机串,每个Pod的地位是同等的
    • 在滚动升级策略上,StatefulSet和Replicaset也是有区别的
  • 扩容时,按序号顺序扩容;缩容时,从大到小缩容。

StatefulSet的控制器,会给创建的Pod添加两个属性:

  • hostname: nginx-ss-序号
  • subdomain: nginx-ss

CoreDNS会把{hostname}.{subdomain}.svc.cluster.local的DNS记录指向nginx-ss-序号 的当前IP

  • 这样Pod就可以通过域名对外提供服务,即使Pod重建更改了IP,这个域名的格式也不会变。
  • 其它服务可以按照这个规则拼接域名,访问指定的Pod

StatefuleSet必须对应一个Service,两者一一对应,互相引用。

StatefulSet的Service必须指定 clusterIP: None,即Headless Service,这样针对每个Pod才会分配独立域名。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
apiVersion: v1
kind: Service
metadata:
  name: nginx-ss
  labels:
    app: nginx-ss
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None # Headless service
  selector:
    app: nginx-ss # 和StatefulSet里的labels匹配
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-with-pvc
spec:
  serviceName: "nginx-ss" # 包含对Service的引用
  replicas: 2
  selector:
    matchLabels:
      app: nginx-ss
  template:
    metadata:
      labels:
        app: nginx-ss
    spec:
      containers:
      - name: nginx-ss
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1M

Job

  • 批处理型任务,完成后自动退出
  • 成功标志根据 spec.completions 策略不同
    • 一个Pod成功即可
    • 定数Pod成功
    • 全部成功
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  parallelism: 2 # 并发数
  completions: 5 # 总执行数
  template:
    spec:
      containers:
        - name: pi
          image: perl
          command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: OnFailure

计算结束后,容器自动停止,但是Pod还在,清单信息和日志也在。

DeamonSet

  • 所有节点/nodeSelector选定节点上保证有一个Pod

Deployment的replicaset 的名字末尾是随机数,⽤于deployment的滚动升级。当deployment的template变化时,⽣成了新的rs,来实现版本控制。

DaemonSet在滚动升级时,也会涉及节点升级、版本变化问题,它是怎么实现版本控制的呢?

  • 随着k8s演进,新的对象的版本升级已经不需要带hash值的rs去控制了,⽽是通过controllerrevision 对象
  • cr中的ownerReference属性记录的它所属对象的信息

当Node故障时,会给Node加Taints,但是DaemonSet的Pod都是能Tolerate的,不会被驱逐。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ds
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

PV/PVC

  • 生命周期与Pod的生命周期无关的

细节见这里

LimitRange

用来约定namespace中Pod的cpu/memory等资源的限制和默认值。

如果Pod没有设置资源使用量,所属的namespace中有一个LimitRange对象,就按该LimitRange中的值设置。

  • 如果Pod中有多个container,每个容器都会有这样的限制。
  • 如果定义了initContainer,会先顺序启动initContainer(调度时只计算需要资源的最大量,不是求和),然后再批量启动主container。

HPA/VPA

应用扩容是指在应用接收到的并发请求已经处于其处理请求极限边界的情况下,扩展处理能力而确保应用高可用的手段。

  • Horizontal Scaling 横向伸缩,通过增加应用实例数量分担负载
  • Vertical Scaling 纵向伸缩,通过增加单个实例资源以提升单个实例处理能力

HPA是k8s的一种资源对象,能够根据某些指标对在StatefulSet、replicaset、deployment等集合中的Pod数量进行横向动态伸缩。HPA依赖于MetricsServer采集运行指标。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler # 自动水平扩缩容
metadata:
  name: php-apache
spec:
  scaleTargetRef: # 处理对象
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1 # 最小Pod数
  maxReplicas: 10
  metrics:  # 指标
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

VPA即垂直Pod自动扩缩容,根据容器资源使用率自动设置CPU和内存request。VPA目前还不够成熟。

其它

Pod的QoS分类

  • Guaranteed
    • Pod的每个容器都设置了CPU和内存需求
    • Limits和requests的值完全一致
  • Burstable
    • 至少一个容器指定了CPU或内存request
    • Pod的资源需求不符合Guaranteed QoS的条件,即request和limit不一致
  • BestEffort
    • Pod中的所有容器都未指定CPU或内存资源需求

当计算节点检测到内存压力时,k8s会按照 BestEffort -> Burstable -> Guaranteed的顺序依次驱逐Pod

实践:

  • 定义Guaranteed的资源需求来保护重要的Pod
  • 根据真实需求设置request和limit,提高集群的资源利用率并减少Pod被驱逐的情况
  • 避免将生产Pod设置为BestEffort

健康检查探针

探针类型:

  • livenessProbe 探活,当检查失败时,会终止容器进程并根据restartPolicy决定是否重启(不会重建)
  • readinessProbe 就绪状态检查,Pod状态标记为NotReady

探测方法:

  • ExecAction 在容器内部执行指定命令
  • TCPSocketAction 检查容器端口
  • HTTPGetAction 对Pod IP的指定端口的指定路径发起HTTPGet请求
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Pod
metadata:
  name: liveness1
spec:
  containers:
    - name: liveness
      image: centos
      args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
      livenessProbe:
        exec:
          command:
            - cat
            - /tmp/healthy
        initialDelaySeconds: 10
        periodSeconds: 5
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
  name: http-probe
spec:
  containers:
    - name: http-probe
      image: nginx
      readinessProbe:
        httpGet:
          ### this probe will fail with 404 error code
          ### only httpcode between 200-400 is retreated as success
          path: /healthz
          port: 80
        initialDelaySeconds: 30
        periodSeconds: 5
        successThreshold: 2

ReadinessGates

引入自定义的就绪条件,相当于一个hook

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: readiness-gate
  name: readiness-gate
spec:
  readinessGates:
    - conditionType: "www.example.com/feature-1"
  containers:
    - name: readiness-gate
      image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: readiness-gate
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: readiness-gate

另外,Pod还可以设置Post-start Hook 和Pre-Stop Hook。