• 容器编排学习(十)控制器介绍与使用


    一  控制器

    控制器是 k8s内置的管理工具。可以帮助用户实现 Pod的自动部署、自维护、扩容、滚动更新等功能的自动化程序。

    为什么要使用控制器?

    • 有大量的 Pod需要维护管理
    • 需要维护 Pod的健康状态
    • 控制器可以像机器人一样可以替用户完成维护管理的工作

    二  Deployment

    1  概述

    最常用的无状态服务控制器,由 Deploymen、ReplicaSet、Pod 组成、支持集群扩容缩容滚动、更新、自动维护 Pod 可用性及·副本量等功能

    ReplicaSet 和 Pod 由 Deployment 自动管理,用户无需干预

    2  Deploy 图例

    3  Deploy 资源文件

    1. # 清理 Pod ,使用控制器创建
    2. [root@master ~]# kubectl delete pod --all
    3. # 资源对象模板
    4. [root@master ~]# kubectl create deployment myweb --image=myos:httpd --dry-run=client -o yaml
    5. [root@master ~]# vim mydeploy.yaml
    6. ---
    7. kind: Deployment # 资源对象类型
    8. apiVersion: apps/v1 # 版本
    9. metadata: # 元数据
    10. name: myweb # 名称
    11. spec: # 详细定义
    12. replicas: 2 # 副本数量
    13. selector: # 定义标签选择器
    14. matchLabels: # 支持 matchExpressions 表达式语法
    15. app: httpd # 通过标签来确定那个 Pod 由它来管理
    16. template: # 定义用来创建 Pod 的模板,以下为 Pod 定义
    17. metadata: # Pod元数据
    18. labels: # 名称由控制器生成
    19. app: httpd # 这里只能定义标签
    20. spec: # Pod的详细定义
    21. restartPolicy: Always # 重启策略
    22. containers: # 容器定义
    23. - name: apache # 容器名称
    24. image: myos:httpd # 创建容器使用的镜像
    25. imagePullPolicy: Always # 镜像下载策略
    26. # 创建 Deployment
    27. [root@master ~]# kubectl apply -f mydeploy.yaml
    28. deployment.apps/myweb created
    29. [root@master ~]# kubectl get deployments
    30. NAME READY UP-TO-DATE AVAILABLE AGE
    31. myweb 2/2 2 2 68s
    32. [root@master ~]# kubectl get replicasets
    33. NAME DESIRED CURRENT READY AGE
    34. myweb-64b544dcbc 2 2 2 73s
    35. [root@master ~]# kubectl get pods
    36. NAME READY STATUS RESTARTS AGE
    37. myweb-64b544dcbc-5mhqn 1/1 Running 0 76s
    38. myweb-64b544dcbc-nt6tz 1/1 Running 0 76s

    4  ClusterIP 服务

    如何访问 Deployment 资源?

    Deployment 管理多个 Pod,可以使用服务对其资源进行访问

    1. # 创建服务访问集群
    2. [root@master ~]# vim websvc.yaml
    3. ---
    4. kind: Service
    5. apiVersion: v1
    6. metadata:
    7. name: websvc
    8. spec:
    9. type: ClusterIP
    10. clusterIP: 10.245.1.80
    11. selector:
    12. app: httpd
    13. ports:
    14. - protocol: TCP
    15. port: 80
    16. targetPort: 80
    17. [root@master ~]# kubectl apply -f websvc.yaml
    18. service/websvc created
    19. [root@master ~]# curl -m 3 http://10.245.1.80
    20. Welcome to The Apache.

     5  Pod维护管理

    1. # 自维护自治理
    2. [root@master ~]# kubectl get pods
    3. NAME READY STATUS RESTARTS AGE
    4. myweb-64b544dcbc-5mhqn 1/1 Running 0 4m16s
    5. myweb-64b544dcbc-nt6tz 1/1 Running 0 4m16s
    6. # Pod 被删除后,Deploy 会自动创建新的 Pod 来维护集群的完整性
    7. [root@master ~]# kubectl delete pod myweb-64b544dcbc-5mhqn
    8. pod "myweb-64b544dcbc-5mhqn" deleted
    9. [root@master ~]# kubectl get pods
    10. NAME READY STATUS RESTARTS AGE
    11. myweb-64b544dcbc-g8l9p 1/1 Running 0 3s
    12. myweb-64b544dcbc-nt6tz 1/1 Running 0 4m25s

    6  集群扩缩容

    1. # 设置 1 Pod 集群
    2. [root@master ~]# kubectl scale deployment myweb --replicas=1
    3. deployment.apps/myweb scaled
    4. [root@master ~]# kubectl get pods
    5. NAME READY STATUS RESTARTS AGE
    6. myweb-64b544dcbc-nt6tz 1/1 Running 0 5m46s
    7. # 设置 3 Pod 集群
    8. [root@master ~]# kubectl scale deployment myweb --replicas=3
    9. deployment.apps/myweb scaled
    10. [root@master ~]# kubectl get pods
    11. NAME READY STATUS RESTARTS AGE
    12. myweb-64b544dcbc-5sf5z 1/1 Running 0 3s
    13. myweb-64b544dcbc-6r6dw 1/1 Running 0 3s
    14. myweb-64b544dcbc-nt6tz 1/1 Running 0 5m56s

    7  历史版本信息

    1. # 查看历史版本
    2. [root@master ~]# kubectl rollout history deployment myweb
    3. deployment.apps/myweb
    4. REVISION CHANGE-CAUSE
    5. 1
    6. # 添加注释信息
    7. [root@master ~]# kubectl annotate deployments myweb kubernetes.io/change-cause="httpd.v1"
    8. deployment.apps/myweb annotated
    9. [root@master ~]# kubectl rollout history deployment myweb
    10. deployment.apps/myweb
    11. REVISION CHANGE-CAUSE
    12. 1 httpd.v1

    8  滚动更新

    1. # 修改镜像,滚动更新集群
    2. [root@master ~]# kubectl set image deployment myweb apache=myos:nginx
    3. deployment.apps/myweb image updated
    4. # 给新版本添加注释信息
    5. [root@master ~]# kubectl annotate deployments myweb kubernetes.io/change-cause="nginx.v1"
    6. deployment.apps/myweb annotated
    7. # 查看历史版本信息
    8. [root@master ~]# kubectl rollout history deployment myweb
    9. deployment.apps/myweb
    10. REVISION CHANGE-CAUSE
    11. 1 httpd.v1
    12. 2 nginx.v1
    13. # 访问验证服务
    14. [root@master ~]# curl -m 3 http://10.245.1.80
    15. Nginx is running !

    9  版本回滚

    1. # 历史版本与回滚
    2. [root@master ~]# kubectl rollout undo deployment myweb --to-revision 1
    3. deployment.apps/myweb rolled back
    4. [root@master ~]# curl -m 3 http://10.245.1.80
    5. Welcome to The Apache.
    6. [root@master ~]# kubectl rollout history deployment myweb
    7. deployment.apps/myweb
    8. REVISION CHANGE-CAUSE
    9. 2 nginx.v1
    10. 3 httpd.v1
    11. # 删除控制器方法1
    12. [root@master ~]# kubectl delete deployments myweb
    13. deployment.apps "myweb" deleted
    14. # 删除控制器方法2
    15. [root@master ~]# kubectl delete -f mydeploy.yaml
    16. deployment.apps "myweb" deleted

    三  DaemonSet

    1  概述

    • 无法自定义副本数量
    • 所创建的 Pod与 node 节点绑定
    • 每个node 上都会运行一个 Pod
    • 当有新 Node 加入集群时,会为他新增 Pod 副本,当 Node 从集群移除时,这些 Pod 也会被回收典型应用:kube-proxy

    2  DS图例

     3  资源对象案例

    1. [root@master ~]# cp -a mydeploy.yaml myds.yaml
    2. [root@master ~]# vim myds.yaml
    3. ---
    4. kind: DaemonSet # 资源对象类型
    5. apiVersion: apps/v1
    6. metadata:
    7. name: myds # 控制器名称
    8. spec:
    9. # replicas: 2 # 删除副本参数
    10. selector:
    11. matchLabels:
    12. app: httpd
    13. template:
    14. metadata:
    15. labels:
    16. app: httpd
    17. spec:
    18. restartPolicy: Always
    19. containers:
    20. - name: apache
    21. image: myos:httpd
    22. imagePullPolicy: Always
    23. # 创建 DaemonSet 资源对象,与 node 绑定,每节点都创建容器
    24. [root@master ~]# kubectl apply -f myds.yaml
    25. daemonset.apps/myds created
    26. [root@master ~]# kubectl get pods -o wide
    27. NAME READY STATUS RESTARTS AGE IP NODE
    28. myds-msrcx 1/1 Running 0 31s 10.244.1.11 node-0001
    29. myds-lwq8l 1/1 Running 0 31s 10.244.2.17 node-0002
    30. myds-4wt72 1/1 Running 0 31s 10.244.3.14 node-0003
    31. myds-6k82t 1/1 Running 0 31s 10.244.4.15 node-0004
    32. myds-9c6wc 1/1 Running 0 31s 10.244.5.19 node-0005

    4  污点干扰

    1. # 设置污点,重建 daemonset
    2. [root@master ~]# kubectl taint node node-0001 k=v:NoSchedule
    3. node/node-0001 tainted
    4. [root@master ~]# kubectl delete -f myds.yaml
    5. daemonset.apps "myds" deleted
    6. [root@master ~]# kubectl apply -f myds.yaml
    7. daemonset.apps/myds created
    8. # 有污点不会部署,特殊需求可以设置容忍策略
    9. [root@master ~]# kubectl get pods
    10. NAME READY STATUS RESTARTS AGE
    11. myds-pkdn9 1/1 Running 0 2s
    12. myds-pkp6b 1/1 Running 0 2s
    13. myds-j84cw 1/1 Running 0 2s
    14. myds-5c69p 1/1 Running 0 2s
    15. # 删除污点后会立即部署
    16. [root@master ~]# kubectl taint node node-0001 k=v:NoSchedule-
    17. node/node-0001 untainted
    18. [root@master ~]# kubectl get pods
    19. NAME READY STATUS RESTARTS AGE
    20. myds-2c86p 1/1 Running 0 1s
    21. myds-pkdn9 1/1 Running 0 9s
    22. myds-pkp6b 1/1 Running 0 9s
    23. myds-j84cw 1/1 Running 0 9s
    24. myds-5c69p 1/1 Running 0 9s
    25. # 删除控制器
    26. [root@master ~]# kubectl delete -f myds.yaml
    27. daemonset.apps "myds" deleted

    四  Job/CronJob

    1  概述

    Job 是一个单任务控制器,负责执行一次任务,保证任务在一个或多个Pod上执行成功

    CronJob 像是Job的升级版,他是基于时间管理的 Job 控制器

    2  Job图例

    3  Job 控制器

    1. # 资源对象模板
    2. [root@master ~]# kubectl create job myjob --image=myos:8.5 --dry-run=client -o yaml -- sleep 3
    3. [root@master ~]# vim myjob.yaml
    4. ---
    5. kind: Job
    6. apiVersion: batch/v1
    7. metadata:
    8. name: myjob # 资源对象名称
    9. spec: # job 的详细定义
    10. template: # 以下定义 Pod 模板
    11. spec: # pod的详细定义
    12. restartPolicy: OnFailure # 只支持[OnFailure,Never]
    13. containers: # 容器定义
    14. - name: myjob # 容器名称
    15. image: myos:8.5 # 创建容器使用的镜像
    16. command: ["/bin/bash"] # 自定义任务,可以使用脚本
    17. args:
    18. - -c
    19. - |
    20. sleep 3
    21. exit $((RANDOM%2))
    22. # restartPolicy 会判断 exit 状态码
    23. # 状态码为 0 表示正常,其他都表示失败
    24. [root@master ~]# kubectl apply -f myjob.yaml
    25. job.batch/myjob created
    26. # 失败了会重启
    27. [root@master ~]# kubectl get pods -l job-name=myjob -w
    28. NAME READY STATUS RESTARTS AGE
    29. myjob--1-lrtbk 1/1 Running 0 2s
    30. myjob--1-lrtbk 0/1 Error 0 4s
    31. myjob--1-lrtbk 1/1 Running 1 (1s ago) 5s
    32. myjob--1-lrtbk 0/1 Completed 1 9s
    33. [root@master ~]# kubectl get jobs.batch
    34. NAME COMPLETIONS DURATION AGE
    35. myjob 1/1 8s 12s
    36. # 删除Job控制器
    37. [root@master ~]# kubectl delete -f myjob.yaml
    38. job.batch "myjob" deleted

    4  CJ图例

     资源对象案例

    1. # 资源对象模板
    2. [root@master ~]# kubectl create cronjob mycj --image=myos:8.5 --schedule='* * * * *' --dry-run=client -o yaml -- sleep 3
    3. [root@master ~]# vim mycj.yaml
    4. ---
    5. kind: CronJob
    6. apiVersion: batch/v1
    7. metadata:
    8. name: mycj # 资源名称
    9. spec: # cronjob 的详细定义
    10. schedule: "* * * * 1-5" # 时间周期:[分、时、日、月、周]
    11. jobTemplate: # 以下定义 Job 模板
    12. spec: # Job的详细定义
    13. template: # 创建pod的模板
    14. spec: # Pod的详细定义
    15. restartPolicy: OnFailure# 只支持[OnFailure,Never]
    16. containers: # 容器定义
    17. - name: myjob # 容器名称
    18. image: myos:8.5 # 创建容器使用的镜像
    19. command: ["/bin/bash"]# 自定义任务
    20. args:
    21. - -c
    22. - |
    23. sleep 3 # 脚本
    24. exit $((RANDOM%2)) # 退出状态码,失败后会重新运行
    25. [root@master ~]# kubectl apply -f mycj.yaml
    26. cronjob.batch/mycj created
    27. # cronjob 会按照时间周期运行
    28. [root@master ~]# kubectl get cronjobs
    29. NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
    30. mycj */1 * * * 1-5 False 0 <none> 4s
    31. # 按照时间周期,每分钟触发一个任务
    32. [root@master ~]# kubectl get jobs -w
    33. NAME READY STATUS RESTARTS AGE
    34. mycj-27808172--1-w6sbx 0/1 Pending 0 0s
    35. mycj-27808172--1-w6sbx 0/1 ContainerCreating 0 0s
    36. mycj-27808172--1-w6sbx 1/1 Running 0 1s
    37. mycj-27808172--1-w6sbx 0/1 Completed 1 4s
    38. # 保留三次结果,多余的会被删除
    39. [root@master ~]# kubectl get jobs
    40. NAME COMPLETIONS DURATION AGE
    41. mycj-27605367 1/1 31s 3m30s
    42. mycj-27605368 1/1 31s 2m30s
    43. mycj-27605369 1/1 31s 90s
    44. mycj-27605370 0/1 30s 30s
    45. [root@master ~]# kubectl get jobs
    46. NAME COMPLETIONS DURATION AGE
    47. mycj-27605368 1/1 31s 2m33s
    48. mycj-27605369 1/1 31s 93s
    49. mycj-27605370 1/1 31s 33s
    50. # 删除CJ控制器
    51. [root@master ~]# kubectl delete -f mycj.yaml
    52. cronjob.batch "mycj" deleted

    五  StatefulSet

    1  概述

    StatefulSet旨在与有状态的应用及分布式系统一起使用,涉及了 Headless 服务、存储卷、DNS 等相关知识点,是一个宽泛而复杂的话题

    2  STS图例

    3  headless服务

    在配置 StatefulSets 的时候首先要定义一个 Headless 的服务。

    在创建 Pod的时候会自动把 注册为域名

    1. # 配置 headless 服务
    2. [root@master ~]# cp websvc.yaml mysvc2.yaml
    3. [root@master ~]# vim mysvc2.yaml
    4. ---
    5. kind: Service
    6. apiVersion: v1
    7. metadata:
    8. name: mysvc2 # 服务名称
    9. spec:
    10. type: ClusterIP
    11. clusterIP: None # 设置 IP 为 None
    12. selector:
    13. app: httpd
    14. ports:
    15. - protocol: TCP
    16. port: 80
    17. targetPort: 80
    18. [root@master ~]# kubectl apply -f mysvc2.yaml
    19. service/mysvc2 created
    20. [root@master ~]# kubectl get service mysvc2
    21. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    22. mysvc2 ClusterIP None <none> 80/TCP 61s

    4  创建 StatefulSets 资源对象文件

    1. [root@master ~]# cp -a mydeploy.yaml mysts.yaml
    2. [root@master ~]# vim mysts.yaml
    3. ---
    4. kind: StatefulSet # 资源对象类型
    5. apiVersion: apps/v1
    6. metadata:
    7. name: mysts # 控制器名称
    8. spec:
    9. serviceName: mysvc2 # 新增 headless 服务名称
    10. replicas: 2
    11. selector:
    12. matchLabels:
    13. app: httpd
    14. template:
    15. metadata:
    16. labels:
    17. app: httpd
    18. spec:
    19. restartPolicy: Always
    20. containers:
    21. - name: apache
    22. image: myos:httpd
    23. imagePullPolicy: Always
    24. [root@master ~]# kubectl apply -f mysts.yaml
    25. statefulset.apps/mysts created
    26. [root@master ~]# kubectl get pods
    27. NAME READY STATUS RESTARTS AGE
    28. mysts-0 1/1 Running 0 2s
    29. mysts-1 1/1 Running 0 1s
    30. # Pod 名称自动注册 DNS 服务
    31. [root@master ~]# host mysts-0.mysvc2.default.svc.cluster.local 10.245.0.10
    32. Using domain server:
    33. Name: 10.245.0.10
    34. Address: 10.245.0.10#53
    35. Aliases:
    36. mysts-0.mysvc2.default.svc.cluster.local has address 10.244.1.81
    37. [root@master ~]# host mysvc2.default.svc.cluster.local 10.245.0.10
    38. Using domain server:
    39. Name: 10.245.0.10
    40. Address: 10.245.0.10#53
    41. Aliases:
    42. mysvc2.default.svc.cluster.local has address 10.244.2.83
    43. mysvc2.default.svc.cluster.local has address 10.244.1.81
    44. # 删除sts控制器
    45. [root@master ~]# kubectl delete -f mysts.yaml -f mysvc2.yaml
    46. statefulset.apps "mysts" deleted
    47. service "mysvc2" deleted

    六  HPA控制器

    1  HorizontalPodAutoscaling概述

    HorizontalPodAutoscaling 简称 HPA,可以在 Kubernetes集群中基于CPU利用率或其他应程序提供的度量指标实现水平自动伸缩的功能,自动缩放POD的数量

    控制器会周期性的获取平均利用率

    与目标值相比较后来调整副本数量

    2  HPA图例

     3  创建后端服务

    1. # 为 Deploy 模板添加资源配额
    2. [root@master ~]# vim mydeploy.yaml
    3. ---
    4. kind: Deployment
    5. apiVersion: apps/v1
    6. metadata:
    7. name: myweb
    8. spec:
    9. replicas: 1 # 修改副本数量
    10. selector:
    11. matchLabels:
    12. app: httpd
    13. template:
    14. metadata:
    15. labels:
    16. app: httpd
    17. spec:
    18. restartPolicy: Always
    19. containers:
    20. - name: apache
    21. image: myos:httpd
    22. imagePullPolicy: Always
    23. resources: # 为该资源设置配额
    24. requests: # HPA 控制器会根据配额使用情况伸缩集群
    25. cpu: 200m # CPU 配额
    26. [root@master ~]# vim websvc.yaml
    27. ---
    28. kind: Service
    29. apiVersion: v1
    30. metadata:
    31. name: websvc
    32. spec:
    33. type: ClusterIP
    34. clusterIP: 10.245.1.80
    35. selector:
    36. app: httpd
    37. ports:
    38. - protocol: TCP
    39. port: 80
    40. targetPort: 80
    41. [root@master ~]# kubectl apply -f mydeploy.yaml -f websvc.yaml
    42. deployment.apps/myweb created
    43. service/websvc created
    44. # 验证服务
    45. [root@master ~]# kubectl top pods
    46. NAME CPU(cores) MEMORY(bytes)
    47. myweb-c8c66f894-2cfjv 1m 17Mi
    48. [root@master ~]# curl -s http://10.245.1.80
    49. Welcome to The Apache.

    4  创建HPA控制器

    1. [root@master ~]# vim myhpa.yaml
    2. ---
    3. kind: HorizontalPodAutoscaler # 资源对象类型
    4. apiVersion: autoscaling/v1 # 版本
    5. metadata: # 元数据
    6. name: myweb # 资源对象名称
    7. spec: # 详细定义
    8. minReplicas: 1 # 最少保留的副本数量
    9. maxReplicas: 5 # 最大创建的副本数量
    10. targetCPUUtilizationPercentage: 50 # 警戒值,以百分比计算
    11. scaleTargetRef: # 监控的资源对象
    12. kind: Deployment # 资源对象类型
    13. apiVersion: apps/v1 # 版本
    14. name: myweb # 资源对象名称
    15. # 创建弹性集群
    16. [root@master ~]# kubectl apply -f myhpa.yaml
    17. horizontalpodautoscaler.autoscaling/myweb created
    18. # 刚刚创建 unknown 是正常现象,最多等待 60s 就可以正常获取数据
    19. [root@master ~]# kubectl get horizontalpodautoscalers.autoscaling
    20. NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
    21. myweb Deployment/myweb <unknown>/50% 1 5 0 4s
    22. # 最多等待 60s 即可正常获取资源状态
    23. [root@master ~]# kubectl get horizontalpodautoscalers.autoscaling
    24. NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
    25. myweb Deployment/myweb 0%/50% 1 5 1 71s

    5  验证测试

    持续访问 Web服务,增加CPU负载,在超过警戒值之后,会触发扩容操作,等待几秒之后发现副本数量增加了。

    停止访问,让CPU空闲,为了防止集群性能抖动,副本不会立即释放,必须300秒内的平均负载小于警戒值,才开始释放副本,当副本达到最小值时候停止释放

    测试时可以通过访问php 脚本增加CPU的负载

    1. # 终端 1 访问提高负载
    2. [root@master ~]# while sleep 1;do
    3. curl -s "http://10.245.1.80/info.php?id=100000" -o /dev/null
    4. done
    5. # 终端 2 监控 HPA 变化
    6. [root@master ~]# kubectl get hpa -w
    7. NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
    8. myweb Deployment/myweb 0%/50% 1 3 1 8m21s
    9. myweb Deployment/myweb 49%/50% 1 3 1 9m
    10. myweb Deployment/myweb 56%/50% 1 3 1 9m15s
    11. myweb Deployment/myweb 56%/50% 1 3 2 9m30s
    12. myweb Deployment/myweb 37%/50% 1 3 2 9m45s
    13. myweb Deployment/myweb 32%/50% 1 3 2 10m
    14. myweb Deployment/myweb 41%/50% 1 3 2 11m
    15. myweb Deployment/myweb 48%/50% 1 3 2 11m
    16. myweb Deployment/myweb 51%/50% 1 3 2 11m
    17. myweb Deployment/myweb 59%/50% 1 3 2 11m
    18. myweb Deployment/myweb 58%/50% 1 3 3 12m
    19. myweb Deployment/myweb 42%/50% 1 3 3 12m
    20. myweb Deployment/myweb 34%/50% 1 3 3 12m
    21. # 如果 300s 内平均负载小于标准值,就会自动缩减集群规模
    22. [root@master ~]# kubectl get hpa -w
    23. NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
    24. myweb Deployment/myweb 38%/50% 1 3 3 19m
    25. myweb Deployment/myweb 21%/50% 1 3 3 20m
    26. myweb Deployment/myweb 17%/50% 1 3 3 21m
    27. myweb Deployment/myweb 7%/50% 1 3 3 22m
    28. myweb Deployment/myweb 0%/50% 1 3 3 23m
    29. myweb Deployment/myweb 0%/50% 1 3 2 25m
    30. myweb Deployment/myweb 0%/50% 1 3 1 28m
  • 相关阅读:
    「DaoCloud 道客」联合华农保险,探索保险机构上云的最佳路径
    网络爬虫之爬虫原理
    操作指南|如何通过Polkassembly参与Moonbeam治理 (2022年8月31日更新)
    Tomcat 正确安装并启动后,浏览器访问localhost8080显示404
    vscode中 vue3+ts 项目的提示失效,volar插件失效问题解决方案
    Git 安全警告修复手册:解决 `fatal: detected dubious ownership in repository at ` 问题 ️
    PHP-FFMpeg 操作音视频
    使用LVGL提升交互效率:基于启明智显Model3A方案的7寸智能屏用户界面(UI)设计介绍
    web前端面试题附答案008-你项目中的TDK是怎么赋值的?(这道题很容易暴露项目经验)
    概述机器学习算法(机器学习)
  • 原文地址:https://blog.csdn.net/2301_79227925/article/details/132768604