K8S三、实战

链接:K8S集群部署

控制器类型 适用场景 Pod特点 有状态/无状态 有序启动 持久存储 适合场景
Deployment 无状态应用 随机名称,无序 无状态 ❌ ❌ Web服务、API
StatefulSet 有状态应用 唯一标识(db-0, db-1) 有状态 ✅ ✅ 数据库、分布式系统
DaemonSet 系统级守护进程 每节点一个副本 无状态 ❌ ❌ 日志收集、监控代理
Job 一次性任务 任务完成后终止 无状态 ❌ ❌ 批处理、数据导入
CronJob 定时任务 周期性执行 无状态 ❌ ❌ 定时备份、日志清理
HPA 自动扩缩容 动态调整副本数 无状态 ❌ ❌ 流量波动大的应用

创建pod

vi nginx-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: default
spec:
  restartPolicy: Never 
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    lifecycle:  # 生命周期钩子
      postStart:  # 容器启动后执行
        exec:
          command: ["/bin/sh", "-c", "echo 'Hello, postStart' > /usr/share/nginx/html/prestop.html"]
      preStop:  # 容器停止前执行
        exec:
          command: ["/bin/sh", "-c", "echo 'Bye, preStop' >> /usr/share/nginx/html/prestop.html"]
    ports:
    - containerPort: 80
    resources:  
      limits:
        cpu: 500m  
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 100Mi  
    workingDir: /usr/share/nginx/html
    startupProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 30
    livenessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 3
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /index.html  # 实际路径是workingDir/index.html
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 3
      timeoutSeconds: 2
      failureThreshold: 3

kubectl apply -f nginx-pod.yaml

kubectl get pod nginx-pod -o yaml 
kubectl get pod nginx-pod -o wide
kubectl describe pods nginx-pod
kubectl exec -it nginx-pod -- sh
kubectl logs nginx-pod

img

创建Deployment

vi deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy  # Deployment名称
  labels:
    app: nginx-deploy
spec:
  replicas: 2  # 期望的Pod副本数
  revisionHistoryLimit: 3  # 保留的历史版本数,默认为10
  selector:
    matchLabels:
      app: nginx  # 选择所有包含app=nginx标签的Pod
  minReadySeconds: 2  # Pod准备就绪前需要等待的最小秒数
  strategy:  # 更新策略
    type: RollingUpdate  # 滚动更新
    rollingUpdate:
      maxUnavailable: 1  # 滚动更新期间最多允许1个Pod不可用  /  25%
      maxSurge: 1  # 滚动更新期间最多允许额外创建1个Pod  /  25%
  template:
    metadata:
      labels:
        app: nginx  # Pod的标签!!!
    spec:  # 期望信息
      restartPolicy: Always  # 重启策略,Always表示总是重新启动,OnFailure表示只有在容器退出时才重新启动,Never表示从不自动重启
      terminationGracePeriodSeconds: 30  # Pod优雅终止的时长,默认为30秒
      containers:
      - name: nginx-pod  # 容器名称
        image: nginx:1.13.0  # 使用的镜像
        imagePullPolicy: IfNotPresent  # 优先使用本地镜像,不存在时才拉取
        ports:
        - containerPort: 80  # 容器内部监听的端口,官方的nginx镜像默认配置为监听 80 端口,而非 8080。即使这里配置的是8080,访问的时候仍然需要使用80端口。
        resources:  # 后续HPA会用到资源限制
          limits:
            cpu: "100m"  # CPU限制为100毫核
          requests:
            cpu: "50m"  # CPU请求为50毫核
kubectl apply -f deployment.yaml
kubectl edit deployment nginx-deploy  # 编辑Deployment并保存,相当于kubectl apply -f deployment.yaml
kubectl get deployment nginx-deploy -owide
NAME           READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES         SELECTOR
nginx-deploy   2/2     2            2           178m   nginx-pod    nginx:1.13.0   app=nginx

kubectl get rs -owide  # ReplicaSet
NAME                      DESIRED   CURRENT   READY   AGE    CONTAINERS   IMAGES         SELECTOR
nginx-deploy-68ff6f9d47   2         2         2       151m   nginx-pod    nginx:1.13.0   app=nginx,pod-template-hash=68ff6f9d47

img

创建StatefulSet

---
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,必须与template.metadata.labels匹配
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx  # 与selector保持一致
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
          name: web

创建DaemonSet

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:  # 新增selector,DaemonSet必须包含
    matchLabels:
      app: logging
      id: fluentd
  template:
    metadata:
      labels:
        app: logging
        id: fluentd
    spec:
      containers:
      - name: fluentd-es
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mirrorgooglecontainers/fluentd-elasticsearch:v2.4.0
        imagePullPolicy: IfNotPresent
        env:
        - name: FLUENTD_ARGS
          value: -qq
        volumeMounts:
        - name: containers
          mountPath: /var/lib/docker/containers
        - name: varlog
          mountPath: /var/log
      volumes:
      - name: containers
        hostPath:
          path: /var/lib/docker/containers
      - name: varlog
        hostPath:
          path: /var/log

node-exporter

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true          # 使用宿主机网络
      hostPID: true              # 可选,用于更详细的进程信息
      containers:
      - name: node-exporter
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/quay.io/prometheus/node-exporter:v1.9.1
        args:
          - "--path.rootfs=/host"
        ports:
          - containerPort: 9100
            name: metrics
        volumeMounts:
          - name: rootfs
            mountPath: /host
            readOnly: true
      volumes:
        - name: rootfs
          hostPath:
            path: /
      tolerations:
        - effect: NoSchedule
          operator: Exists

prometheus

---
apiVersion: v1  # 资源的 API 版本(core/v1 核心组,命名空间是基础资源)
kind: Namespace  # 资源类型:命名空间(用于资源隔离)
metadata:
  name: monitoring  # 命名空间名称:所有 Prometheus 相关资源都放在这个命名空间下
---
apiVersion: v1  # API 版本(core/v1)
kind: ServiceAccount  # 资源类型:服务账户(Pod 访问集群资源的身份凭证)
metadata:
  name: prometheus  # 服务账户名称
  namespace: monitoring  # 所属命名空间
---
apiVersion: rbac.authorization.k8s.io/v1  # RBAC 相关资源的 API 版本
kind: ClusterRole  # 资源类型:集群角色(集群级别的权限集合,跨命名空间)
metadata:
  name: prometheus  # 集群角色名称
rules:  # 权限规则列表(定义允许操作的资源和动作)
- apiGroups: [""]  # API 组:空字符串表示核心 API 组(如 Pod、Service 等基础资源)
  resources: ["nodes", "services", "endpoints", "pods"]  # 允许操作的资源类型
  verbs: ["get", "list", "watch"]  # 允许执行的动作:查询(get)、列表(list)、监听(watch)
---
apiVersion: rbac.authorization.k8s.io/v1  # RBAC API 版本
kind: ClusterRoleBinding  # 资源类型:集群角色绑定(将 ClusterRole 绑定到 ServiceAccount)
metadata:
  name: prometheus  # 绑定名称
roleRef:  # 引用要绑定的角色
  apiGroup: rbac.authorization.k8s.io  # 角色所属的 API 组
  kind: ClusterRole  # 角色类型(这里是 ClusterRole)
  name: prometheus  # 角色名称(对应上面创建的 ClusterRole)
subjects:  # 绑定的对象(给谁分配这个角色)
- kind: ServiceAccount  # 对象类型:服务账户
  name: prometheus  # 服务账户名称(对应上面创建的 ServiceAccount)
  namespace: monitoring  # 服务账户所属的命名空间
---
apiVersion: v1  # API 版本(core/v1)
kind: ConfigMap  # 资源类型:配置映射(存储非敏感配置数据)
metadata:
  name: prometheus-config  # ConfigMap 名称
  namespace: monitoring  # 所属命名空间
data:  # 核心配置数据(key-value 结构,key 是文件名,value 是文件内容)
  prometheus.yml: |  # 配置文件名称:prometheus.yml(Prometheus 的核心配置文件)
    global:  # 全局配置
      scrape_interval: 15s  # 指标采集间隔:每 15 秒采集一次所有目标
    scrape_configs:  # 采集配置列表(定义要采集哪些目标的指标)
      - job_name: 'prometheus'  # 采集任务名称:采集 Prometheus 自身指标
        static_configs:  # 静态配置(固定采集目标)
          - targets: ['localhost:9090']  # 采集目标:Prometheus 容器内的 9090 端口(自身指标接口)
      - job_name: 'node-exporter'  # 采集任务名称:采集 node-exporter 的节点指标
        kubernetes_sd_configs:  # Kubernetes 服务发现(自动发现集群内的节点)
          - role: node  # 服务发现角色:node(自动发现所有集群节点)
        relabel_configs:  # 标签重写(修改采集目标的地址)
          - source_labels: [__address__]  # 源标签:K8s 自动发现的节点地址(格式:节点IP:443)
            regex: '(.*):.*'  # 正则表达式:匹配「IP:任意端口」,提取 IP 部分(分组 1)
            target_label: __address__  # 目标标签:覆盖采集目标的地址
            replacement: '${1}:9100'  # 替换值:用提取的节点 IP + node-exporter 的默认端口 9100
---
apiVersion: apps/v1  # API 版本(apps/v1,用于部署类资源)
kind: Deployment  # 资源类型:Deployment(管理 Pod 的创建、更新、回滚)
metadata:
  name: prometheus  # Deployment 名称
  namespace: monitoring  # 所属命名空间
spec:  # Deployment 规格
  replicas: 1  # 副本数:1(单实例部署,极简场景够用)
  selector:  # 选择器(匹配要管理的 Pod)
    matchLabels:
      app: prometheus  # 匹配标签为「app: prometheus」的 Pod
  template:  # Pod 模板(定义要创建的 Pod 的规格)
    metadata:
      labels:
        app: prometheus  # Pod 的标签(必须与上面的 selector.matchLabels 一致)
    spec:  # Pod 规格
      serviceAccountName: prometheus  # 关联的服务账户(对应上面创建的 ServiceAccount)
      containers:  # 容器列表(这里只有一个 Prometheus 容器)
      - name: prometheus  # 容器名称
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/rancher/mirrored-prometheus-prometheus:v2.50.1  # Prometheus 镜像地址(华为云镜像仓库的镜像,避免拉取失败)
        args:  # 容器启动参数(传递给 Prometheus 程序的参数)
          - '--config.file=/etc/prometheus/prometheus.yml'  # 指定配置文件路径(挂载的 ConfigMap 路径)
          - '--storage.tsdb.path=/prometheus'  # 指标数据存储路径(挂载的 emptyDir 目录)
        ports:  # 容器暴露端口
          - containerPort: 9090  # Prometheus 的默认端口(UI 和指标接口都通过该端口暴露)
        volumeMounts:  # 容器内挂载卷(将 ConfigMap 和 emptyDir 挂载到容器目录)
          - name: config  # 卷名称(对应下面 volumes 中的 config)
            mountPath: /etc/prometheus  # 挂载到容器内的目录(配置文件所在目录)
          - name: data  # 卷名称(对应下面 volumes 中的 data)
            mountPath: /prometheus  # 挂载到容器内的目录(数据存储目录)
      volumes:  # Pod 卷定义(提供存储给容器)
        - name: config  # 卷名称
          configMap:  # 卷类型:ConfigMap(关联上面创建的 Prometheus 配置)
            name: prometheus-config  # 关联的 ConfigMap 名称
        - name: data  # 卷名称
          emptyDir: {}  # 卷类型:emptyDir(临时存储,Pod 重启后数据丢失)
---
apiVersion: v1  # API 版本(core/v1)
kind: Service  # 资源类型:Service(暴露 Pod 访问入口,实现负载均衡)
metadata:
  name: prometheus  # Service 名称
  namespace: monitoring  # 所属命名空间
spec:  # Service 规格
  type: NodePort  # 新增:指定 Service 类型为 NodePort
  selector:  # 选择器(匹配要暴露的 Pod)
    app: prometheus  # 匹配标签为「app: prometheus」的 Pod(对应 Deployment 创建的 Pod)
  ports:  # 端口映射
    - port: 9090  # Service 暴露的端口(集群内可通过该端口访问)
      targetPort: 9090  # 目标端口(Pod 容器暴露的端口,对应上面的 containerPort)
      nodePort: 30090  # 固定 NodePort(可选,不指定则自动分配)

滚动升级和回滚

Deployment 是如何利用 ReplicaSet 实现滚动更新的?
当你更新 Deployment 的镜像版本时:

1. Deployment 会创建一个新的 ReplicaSet(对应新版本)。

2. 新 RS 慢慢增加 Pod 数量(扩容)。

3. 旧的 ReplicaSet 慢慢减少 Pod 数量(缩容)。

4. 直到新 RS 的 Pod 数量达到期望值,旧 RS 的 Pod 数量降为 0。

5. 旧 RS 不会被删除,而是保留下来(副本数为 0),方便你随时回滚。
  • deployment
vi deployment.yaml
image: nginx:1.13.0  >>  image: nginx:latest  # 修改镜像版本

kubectl annotate deployments.apps nginx-deploy kubernetes.io/change-cause="Update Something"  # 记录此次更新,以便日后回滚
kubectl rollout status deployment nginx-deploy  # 查看滚动升级状态
kubectl rollout history deployment/nginx-deploy  # 查看历史版本
kubectl rollout history deployment/nginx-deploy --revision=3  # 查看指定版本的历史记录

# 回滚到上一个版本(无需指定版本号)
kubectl rollout undo deployment nginx-deploy
# 或回滚到指定版本(需确认版本号存在)
kubectl rollout undo deployment nginx-deploy --to-revision=2
kubectl rollout status deployment nginx-deploy  # 查看回滚状态

kubectl rollout pause deployment <name>  # 暂停滚动升级
kubectl rollout resume deployment <name>  # 恢复滚动升级

img

  • statefulSet
kubectl edit statefulsets.apps web

  updateStrategy:
    rollingUpdate:
      partition: 3  # 滚动更新时,只有序号大于等于3的Pod会被更新
    type: RollingUpdate
kubectl edit statefulsets.apps web

  updateStrategy:
    type: OnDelete  # 设置为 OnDelete,只有在手动删除 Pod 后才会创建新的 Pod

扩缩容、非级联删除

kubectl scale deployment nginx-deploy --replicas=6
kubectl scale statefulset web --replicas=6
非级联删除,删除Deployment或StatefulSet时不会自动删除其管理的Pod
kubectl delete deployment nginx-deploy --cascade=false
kubectl delete statefulset web --cascade=false

img

创建serivce

vi service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc  # Service的名称,在同一个命名空间内必须唯一
  labels:
    app: nginx
spec:
  type: NodePort
  ports:
  - port: 80  # Service 在集群内部的端口(其他 Pod 通过此端口访问该服务)
    nodePort: 30080  # 节点上暴露的端口,外部可通过 <NodeIP>:30080 访问服务,范围是30000-32767。
    protocol: TCP
  selector:
    app: nginx  # selector下的app标签要和Pod的label一致
kubectl apply -f service.yaml

以下两个地方要注意,要保持一致
service.yaml --> spec.selector
deployment.yaml  --> spec.template.metadata.labels

label 和 Selector
  标签(Label)
    配置文件
    kubectl 
      kubectl label po <资源名称> app=hello  # 临时创建 label
      kubectl label po <资源名称> app=hello2 --overwrite  # 覆盖原有 label
      kubectl get po -A -l app=hello
      kubectl get po --show-labels
  选择器(Selector)
    配置文件
    kubectl
      kubectl get po -A -l app=hello  # 筛选标签为 app=hello 的 Pod
      kubectl get po -A -l 'k8s-app in (metrics-server, kubernetes-dashboard)'  # 筛选标签为 k8s-app=metrics-server 或 k8s-app=kubernetes-dashboard 的 Pod
      kubectl get po -l version!=1,app=nginx  # 筛选标签为 version!=1 且 app=nginx 的 Pod
      kubectl get po -A -l version!=1,'app in (busybox, nginx)'  # 筛选标签为 version!=1 且 app=busybox 或 app=nginx 的 Pod
kubectl describe svc nginx-svc 
Name:                     nginx-svc
Namespace:                default
Labels:                   app=nginx
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.160.27
IPs:                      10.100.160.27
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                10.240.214.207:80,10.240.214.208:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Endpoint 是Service和Pod之间的桥梁,它记录了哪些Pod可以被访问。

访问Service

Service 的网络标识:ClusterIP、DNS 名称

kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        43h
nginx-svc    NodePort    10.100.160.27   <none>        80:30080/TCP   18h

NAME: nginx-svc
CLUSTER-IP: 10.100.160.27
PORT:80
NodePort: 30080
从集群内部,可以通过前3个值(Name、ClusterIP、port)来直接访问
从集群外部,可以通过NodeIP:NodePort来访问

curl 10.100.160.27:80 # 集群内部访问Service
curl nginx-svc:80 # Pod内部通过DNS访问Service
curl 1.1.1.100:30080 # 集群外部访问Service es100:30800
img

HPA

前提条件:部署nginx,可参考上面的Deployment和Service部分

vi metric-server.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"
  name: system:aggregated-metrics-reader
rules:
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
rules:
- apiGroups:
  - ""
  resources:
  - nodes/metrics
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/metrics-server/metrics-server:v0.6.4
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /livez
            port: https
            scheme: HTTPS
          periodSeconds: 10
        name: metrics-server
        ports:
        - containerPort: 4443
          name: https
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /readyz
            port: https
            scheme: HTTPS
          initialDelaySeconds: 20
          periodSeconds: 10
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        volumeMounts:
        - mountPath: /tmp
          name: tmp-dir
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      volumes:
      - emptyDir: {}
        name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  labels:
    k8s-app: metrics-server
  name: v1beta1.metrics.k8s.io
spec:
  group: metrics.k8s.io
  groupPriorityMinimum: 100
  insecureSkipTLSVerify: true
  service:
    name: metrics-server
    namespace: kube-system
  version: v1beta1
  versionPriority: 100
kubectl apply -f metric-server.yaml

kubectl autoscale deployment nginx-deploy --cpu-percent=50 --min=2 --max=10  # 创建HPA,自动扩容,CPU使用率超过50%,最小2个Pod,最大10个Pod
kubectl delete hpa nginx-deploy  # 删除HPA
horizontalpodautoscaler.autoscaling/nginx-deploy autoscaled  # 查看HPA状态

测试开始:使用一下Python代码进行连接模拟

原本是来模拟http版本请求的,凑合着用吧

import time
import httpx
import ssl

while True:
    with httpx.Client(http2=False, verify=False) as client:  # http2=True则使用 HTTP2,http2=False,则默认采用 HTTP/1.1 协议
        response = client.get('http://1.1.1.100:30080', headers={'Host': url})
        response = client.get('http://1.1.1.80:30080', headers={'Host': url})
        time.sleep(1)  # 这里可以自由调节,间隔越小,CPU使用率越高

观测结果:

kubectl get hpa nginx-deploy --watch  # 观察HPA自动扩容


kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-74db4c6d6f-65lzx   1/1     Running   0          16h
nginx-deploy-74db4c6d6f-kzwvn   1/1     Running   0          5m11s
nginx-deploy-74db4c6d6f-xf99c   1/1     Running   0          16h
nginx-deploy-74db4c6d6f-xv9hc   1/1     Running   0          5m11s


kubectl get hpa nginx-deploy --watch
NAME           REFERENCE                 TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx-deploy   Deployment/nginx-deploy   0%/50%    2         10        2          19h
nginx-deploy   Deployment/nginx-deploy   38%/50%   2         10        2          19h
nginx-deploy   Deployment/nginx-deploy   92%/50%   2         10        2          19h
nginx-deploy   Deployment/nginx-deploy   106%/50%   2         10        4          19h
nginx-deploy   Deployment/nginx-deploy   72%/50%    2         10        4          19h
nginx-deploy   Deployment/nginx-deploy   0%/50%     2         10        4          19h

nginx-deploy   Deployment/nginx-deploy   0%/50%     2         10        4          19h
nginx-deploy   Deployment/nginx-deploy   0%/50%     2         10        2          19h

img

不可调度与驱逐POD

  • 当前状态
    kubectl get pod -owide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    nginx-deploy-74db4c6d6f-65lzx 1/1 Running 0 16h 10.240.214.208 es80
    nginx-deploy-74db4c6d6f-xf99c 1/1 Running 0 16h 10.240.214.207 es80

  • 配置禁止调度
    kubectl cordon es80
    继续执行上述的Python脚本,然后观测kubectl get hpa nginx-deploy --watch
    观测到新的POD都创建在es90上
    img

脚本停止后,又恢复为2个POD

  • 驱逐

修改deployment.yaml,将replicas改为6后apply。
kubectl apply -f deployment.yaml

现在要把es90的POD驱逐到es80上,执行kubectl drain es90 --ignore-daemonsets

img

排障

镜像无法拉取

https://docker.aityp.com/

方式一:docker拉取再导入

docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.13.0  # 华为云镜像仓库拉取镜像

docker tag  swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.13.0  docker.io/nginx:1.13.0  # 打标签

docker save docker.io/nginx:1.13.0 -o nginx.tar  # 导出镜像

ctr -n k8s.io images import nginx.tar  # 导入镜像

crictl images
报错
crictl images
WARN[0000] image connect using default endpoints: [unix:///var/run/dockershim.sock unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock unix:///var/run/cri-dockerd.sock]. As the default settings are now deprecated, you should set the endpoint instead. 
E1127 16:49:36.363810   96670 remote_image.go:119] "ListImages with filter from image service failed" err="rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory\"" filter="&ImageFilter{Image:&ImageSpec{Image:,Annotations:map[string]string{},},}"
FATA[0000] listing images: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory" 

原因:crictl 默认尝试连接多个 CRI(Container Runtime Interface)端点,但你的系统中 没有运行 Docker(或 dockershim),而 /var/run/dockershim.sock 文件不存在,导致连接失败。

修复:
sudo tee /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

方式二:使用镜像加速源

img

BackOff

现象/告警:Warning BackOff 109s (x9 over 3m23s) kubelet Back-off restarting failed container

原因:BackOff 警告,说明启动失败后 kubelet 不断重试 --> 容器启动后立即退出

可能的原因:

  1. 架构不匹配(最可能!)
    kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}' # 查看架构
    修改镜像的架构

pod访问不通

现象/告警:Error from server: error dialing backend: dial tcp 192.168.248.12:10250: connect: no route to host

posted @ 2025-07-17 11:18  WiseHYH  阅读(144)  评论(0)    收藏  举报