【kubernetes系列】Kubernetes之Ingress

news2024/11/18 17:33:27

概述

从前面的学习,我们可以了解到Kubernetes暴露服务的方式目前常见的只有三种:LoadBlancer Service、NodePort Service、Ingress;而我们需要将集群内服务提供外界访问就会面临以下几个问题:

Pod 漂移问题
Kubernetes 具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动启动一个新的,还可以进行动态扩容等。那么自然随着 Pod 的销毁和创建,Pod IP 也会动态变化;那么通过Pod IP去访问某个服务的话是不现实的,而且如果是多个pod实例,怎么做到负载均衡呢?这里借助于 Kubernetes 的 Service 机制,Service 可以以标签的形式选定一组带有指定标签的 Pod,并监控和自动负载他们的 Pod IP,那么我们向外暴露只暴露 Service IP 就行了;这就是 NodePort 模式:即在每个节点上开起一个端口,然后转发到内部 Pod IP 上。

端口管理问题
如果采用 NodePort 方式暴露服务需要的面临问题是,服务一旦多起来,NodePort 在每个节点上开启的端口会及其庞大,而且很容易造成端口冲突,效率低,难以维护。这时,我们可以在前端部署一个Nginx Pod直接对内进行转发。因为Pod与Pod之间是可以互相通信的,而Pod是可以共享宿主机的网络名称空间的,也就是说当在共享网络名称空间时,Pod上所监听的就是Node上的端口。那么这又该如何实现呢?简单的实现就是使用 DaemonSet 在每个 Node 上监听 80,然后写好规则,因为 Nginx 外面绑定了宿主机 80 端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应 Service IP 就行了。

域名分配及动态更新问题
从上面的方法,采用 Nginx Pod 似乎已经解决了问题,但是其实这里面有一个很大缺陷:当每次有新服务加入又该如何修改 Nginx 配置呢??我们知道使用Nginx可以通过虚拟主机域名进行区分不同的服务,而每个服务通过upstream进行定义不同的负载均衡池,再加上location进行负载均衡的反向代理,在日常使用中只需要修改nginx.conf即可实现,那在K8S中又该如何实现这些配置呢???

假设后端的服务初始服务只有api,后面增加了web和docs服务,那么又该如何将这2个服务加入到Nginx Pod进行调度呢?总不能每次手动去修改nginx的相关配置然后重启nginx的pod吧!!此时 Ingress 出现了,Ingress 包含两大组件:Ingress Controller 和 Ingress。

Ingress是kubernetes中的一种资源对象,作用是定义请求如何转发到service的规则,简单的理解就是你原来需要改 Nginx 配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改 Nginx 了,直接改 yaml 然后创建/更新就行了;那么问题来了:”Nginx 该怎么处理?”

而Ingress Controller 这东西就是解决 “Nginx 的处理方式” 的;Ingress Controoler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后对它进行解析,按照它自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下,工作流程如下图:

在这里插入图片描述

Ingress Controller的实现方式常见的有两种,nginx和traefik,工作架构如下,借用traefik官方的图:

ingress-5
ingress-5

通过设置可以将api.domain.com进来的流量路由到集群里api的pod上,你可以将domain.com/web流量路由到web的一组pod上(注意:ingress nginx是怎么识别那些Pod是那个应该加入那个upstream呢?这里就用到了service使用service的labels将一组服务关联起来,虽然创建了service但是ingress controller在解析service的是时候实际是解析到后面的Pod上。)

ingress-6
ingress-6

看起来按照nginx来理解转发是client——>nginx——>svc——>pod;
实际上转发是client—–>nginx——>pod,是直接负载到svc后面的Pod上面的

部署Ingress (以 nginx-ingress为例)

选择适合自己k8s集群版本的nginx-ingress,具体可以参考https://github.com/kubernetes/ingress-nginx/tree/controller-v1.8.1,大致如下:

Ingress-NGINX versionk8s supported versionAlpine VersionNginx VersionHelm Chart Version
v1.8.11.27,1.26, 1.25, 1.243.18.21.21.64.7.*
v1.8.01.27,1.26, 1.25, 1.243.18.01.21.64.7.*
v1.7.11.27,1.26, 1.25, 1.243.17.21.21.64.6.*
v1.7.01.26, 1.25, 1.243.17.21.21.64.6.*
v1.6.41.26, 1.25, 1.24, 1.233.17.01.21.64.5.*
v1.5.11.25, 1.24, 1.233.16.21.21.64.4.*
v1.4.01.25, 1.24, 1.23,1.223.16.21.19.10+4.3.0
v1.3.11.24, 1.23, 1.22, 1.21, 1.203.16.21.19.10+4.2.5
v1.3.01.24, 1.23, 1.22, 1.21, 1.203.16.01.19.10+4.2.3
v1.2.11.23, 1.22, 1.21, 1.20, 1.193.14.61.19.10+4.1.4
v1.1.31.23, 1.22, 1.21, 1.20, 1.193.14.41.19.10+4.0.19
v1.1.21.23, 1.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.18
v1.1.11.23, 1.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.17
v1.1.01.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.13
v1.0.51.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.9
v1.0.41.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.6
v1.0.31.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.5
v1.0.21.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.3
v1.0.11.22, 1.21, 1.20, 1.193.14.21.19.9+4.0.2
v1.0.01.22, 1.21, 1.20, 1.193.13.51.20.14.0.1

由于我的kubernetes版本比较老为1.19.16,按表看应该是nginx版本大于1.19.10的都可以
部署Ingress的步骤:(注意先后顺序,如果先执行了mandatory.yaml文件在执行service-nodeport.yaml文件使用kubectl logs -f 看ingress-controller的pod的日志会有很多报错信息)

1)下载Ingress-controller相关的yaml文件,并给Ingress-controller创建独立的名称空间命名为ingress-nginx;
2)按需修改下载的yaml文件
3)创建Ingress-controller的service,以实现接入集群外部流量;
4)部署Ingress-controller;
5)部署后端的服务,如nginx,并通过service进行暴露;
6)部署Ingress,编写规则,使Ingress-controller和后端服务的Pod组进行关联。

1)下载yaml文件

#部署nginx ingress服务的yaml文件
[root@k8s-m1 nginx-ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.0/deploy/mandatory.yaml
#用于暴露服务供外部用户访问
[root@k8s-m1 nginx-ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.0/deploy/provider/baremetal/service-nodeport.yaml

2)修改yaml文件
入口nginx-ingress的访问方式有两种

  • 可以用nodeport的方式暴露端口
  • 通过设置 hostNetwork为true直接使用宿主机的网络空间
#添加了nodeport的端口,主要为了固定端口
[root@k8s-m1 nginx-ingress]# cat  service-nodeport.yaml 
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 30080
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
      nodePort: 30443
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

3)部署Ingress Nginx

[root@k8s-m1 nginx-ingress]# kubectl apply  -f service-nodeport.yaml -f mandatory.yaml 
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created

#检查部署情况,pod是否正常,日志是否有报错等
[root@k8s-m1 nginx-ingress]# kubectl get po -n ingress-nginx 
NAME                                       READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-7c9bd444c-bhsvn   1/1     Running   0          113s
[root@k8s-m1 nginx-ingress]# kubectl logs -n ingress-nginx nginx-ingress-controller-7c9bd444c-bhsvn 

4)创建后端服务用于测试

[root@k8s-m1 nginx-ingress]# cat nginx-deployment.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      tier: frontend
  replicas: 2
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
        - name: nginx-gateway
          image: nginx
          ports:
            - containerPort: 80
[root@k8s-m1 nginx-ingress]# cat nginx-svc.yml 
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 80
  selector:
    tier: frontend

[root@k8s-m1 nginx-ingress]# kubectl apply -f nginx-deployment.yml -f  nginx-svc.yml 

5)创建ingress
ingress资源定义格式查看

[root@k8s-m1~]# kubectl explain ingress

编写ingress的配置清单:

[root@k8s-m1 nginx-ingress]# cat my-nginx-ingress.yml 
apiVersion: extensions/v1beta1
kind: Ingress      
metadata:         
  name: ingress-fronted
  annotations:         
    kubernetes.io/ingress.class: "nginx"
spec:     
  rules: 
  - host: nginx.margu.com    
    http:
      paths:       
      - path:       #配置访问路径,如果通过url进行转发,需要修改;空默认为访问的路径为"/"
        backend:    #配置后端服务
          serviceName: nginx-service
          servicePort: 80  #注意端口要与之前svc里面的一致

进入ingress nginx的pod可以看到nginx的配置里面已经有根据ingress规则生成的相关配置信息,如下:

[root@k8s-m1 nginx-ingress]# kubectl exec -it -n ingress-nginx nginx-ingress-controller-7c9bd444c-bhsvn -- /bin/bash
www-data@nginx-ingress-controller-7c9bd444c-bhsvn:/etc/nginx$ cat nginx.conf|more
        ## start server nginx.margu.com
        server {
                server_name nginx.margu.com ;

                listen 80;

                set $proxy_upstream_name "-";

                location / {

                        set $namespace      "default";
                        set $ingress_name   "ingress-fronted";
                        set $service_name   "nginx-service";
                        set $service_port   "80";
                        set $location_path  "/";

                        rewrite_by_lua_block {
                                balancer.rewrite()
                        }

                        header_filter_by_lua_block {

                        }
                        body_filter_by_lua_block {

                        }

                        log_by_lua_block {

                                balancer.log()

                                monitor.call()

                        }

找一台非集群的机器,向hosts文件内添加域名nginx.margu.com设置到集群的任意一个node节点ip上(因为我们使用的是nodeport的方式暴露的ingress nginx,所以每个节点都会有端口暴露出来),打开浏览器访问nginx.margu.com即可发现集群内的nginx已经暴露在集群外。如下:

配置域名解析(Node节点IP),如我的环境以下任意一条域名解析都是可以的

192.168.2.140 nginx.margu.com
192.168.2.141 nginx.margu.com
192.168.2.142 nginx.margu.com

6)多个Ingress controllers:
如果环境中运行多个Ingress controllers,则需要kubernetes.io/ingress.class: "nginx"指定将ingress对象加入到那个Ingress

controllers中
metadata:
  name: foo
  annotations:
    kubernetes.io/ingress.class: "pre"

将以pre控制器作为目标,使它忽略其他种类控制器。

metadata:
  name: foo
  annotations:
    kubernetes.io/ingress.class: "pro"

将以pro控制器作为目标,使它忽略其他种类控制器。

Rewrite(重写):
必须条件:当集群中有多个Ingress controller时需要通过指定Ingress.class注释来确保您的Ingress只针对一个Ingress controller生效,并且的集群中必须运行着这个Ingress controller。ingress可以使用以下标签来控制重写,详情可参考官网https://kubernetes.github.io/ingress-nginx/examples/rewrite/

名称描述
nginx.ingress.kubernetes.io/rewrite-targetTarget URI where the traffic must be redirectedstring
nginx.ingress.kubernetes.io/ssl-redirectIndicates if the location section is only accessible via SSL (defaults to True when Ingress contains a Certificate)bool
nginx.ingress.kubernetes.io/force-ssl-redirectForces the redirection to HTTPS even if the Ingress is not TLS Enabledbool
nginx.ingress.kubernetes.io/app-rootDefines the Application Root that the Controller must redirect if it’s in / contextstring
nginx.ingress.kubernetes.io/use-regexIndicates if the paths defined on an Ingress use regular expressionsbool

7)配置无host字段ingress

[root@k8s-m1 nginx-ingress]# cat no-domain-ingress.yml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: no-domain-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/server-alias: "nginx.margu.com"
    nginx.ingress.kubernetes.io/use-regex: "true"   #支持nginx的rui的正则匹配
spec:
  rules:
  - http:
      paths: 
      - path: /(.*)
        backend:
          serviceName: nginx-service
          servicePort: 80
[root@k8s-m1 nginx-ingress]# 

在配置中我们没有host字段,这将在ingress-nginx配置中会以如下形式展示,此种方式我们可以用IP或域名的方式访问,因为我们还配置了nginx.ingress.kubernetes.io/server-alias: “nginx.margu.com”,所以当我们用域名访问时用nginx.margu.com访问。
但是需要注意的是,在使用无域名的Ingress转发规则时,将默认使用HTTPS安全协议进行转发。如需使用非安全的HTTP,还需要额外调整Ingress Controller的相关配置,通常在一个安全的网络环境下使用。

        ## start server _
        server {
                server_name _ nginx.margu.com;

                listen 80 default_server reuseport backlog=4096;

                set $proxy_upstream_name "-";

                listen 443  default_server reuseport backlog=4096 ssl http2;

                # PEM sha: e177c1bdc45a48a1cd43a53bd559f8254c442ce7
                ssl_certificate                         /etc/ingress-controller/ssl/default-fake-certificate.pem;
                ssl_certificate_key                     /etc/ingress-controller/ssl/default-fake-certificate.pem;

                location ~* "^/(.*)" {

                        set $namespace      "default";
                        set $ingress_name   "no-domain-ingress";
                        set $service_name   "nginx-service";
                        set $service_port   "80";
                        set $location_path  "/(.*)";

构建TLS站点

为了安全起见,我们一般都是要求客户端通过https进行访问,下面我们进行测试。注意:我们需要标准证书格式,不能将key+server+ca放在一个pem文件中。
1)准备证书

[root@k8s-m1 nginx-ingress]# openssl genrsa -out tls.key 2048 
Generating RSA private key, 2048 bit long modulus
.......+++
.......................................................................+++
e is 65537 (0x10001)
[root@k8s-m1 nginx-ingress]#  openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=nginx.margu.com

2)生成secret

[root@k8s-m1 nginx-ingress]# kubectl create secret tls nginx-ingress-secret --cert=tls.crt --key=tls.key
secret/nginx-ingress-secret created
[root@k8s-m1 nginx-ingress]# kubectl get secret
NAME                                  TYPE                                  DATA   AGE
nginx-ingress-secret                  kubernetes.io/tls                     2      8s
[root@k8s-m1 nginx-ingress]# kubectl describe secret nginx-ingress-secret 
Name:         nginx-ingress-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1289 bytes
tls.key:  1679 bytes

3)ingress规则定义并部署

[root@k8s-m1 nginx-ingress]# cat  my-nginx-tls-ingress.yml 
apiVersion: extensions/v1beta1
kind: Ingress      
metadata:         
  name: ingress-fronted
  annotations:         
    kubernetes.io/ingress.class: "nginx"
spec:     
  tls:
  - hosts:
    - nginx.margu.com
    secretName: nginx-ingress-secret
  rules: 
  - host: nginx.margu.com    
    http:
      paths:       
      - path:       #配置访问路径,如果通过url进行转发,需要修改;空默认为访问的路径为"/"
        backend:    #配置后端服务
          serviceName: nginx-service
          servicePort: 80

[root@k8s-m1 nginx-ingress]# kubectl  apply -f my-nginx-tls-ingress.yml 
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/ingress-fronted-tls created
[root@k8s-m1 nginx-ingress]# kubectl get ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME                  CLASS    HOSTS             ADDRESS   PORTS     AGE
ingress-fronted       <none>   *                           80        24m
ingress-fronted-tls   <none>   nginx.margu.com             80, 443   16s

4)访问测试:https://nginx.margu.com:30443
在这里插入图片描述

5)不想添加端口访问,改使用正常的80/443端口进行访问

#先删除开始nginx-ingress的nodeport暴露方式
[root@k8s-m1 nginx-ingress]# kubectl delete -f nginx-svc.yml 

#修改yaml,在template下面spec处添加hostNetwork和hostPID,如下
[root@k8s-m1 nginx-ingress]# vim mandatory.yaml 
    spec:
      hostNetwork: true
      hostPID: true
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.23.0
......

[root@k8s-m1 nginx-ingress]# kubectl apply  -f mandatory.yaml 

[root@k8s-m1 nginx-ingress]# kubectl get po -n ingress-nginx -o wide
NAME                                        READY   STATUS        RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
nginx-ingress-controller-554586bf4d-74pp2   1/1     Running       0          30s     192.168.2.142   k8s-m3   <none>           <none>
I

测试:此种方法只会在nginx-ingress 的pod所在节点上暴露端口80和443,所以在本地hosts中添加域名解析时需要注意IP地址。如上,需要解析到192.168.2.142这个IP地址。实际使用中,我们可以通过打标签的方式在多个节点部署nginx-ingess的示例,然后通过前端负载均衡器进行负载。

hosts:192.168.2.142 nginx.margu.com
在这里插入图片描述

Ingress Controller高可用

在实际使用中,为保证服务的高可用和负载均衡,我们往往需要部署多个nginx-ingress的pod,并使用haproxy+keepalived或者某些平台自带的负载均衡器进行负载。上面的例子里入口ingress-nginx使用的是nodePort的方式,Nodeport端口不是常用的web端口(但是可以修改Nodeport的范围改成web端口),如果当流量进来负载到某个node上的时候因为Ingress Controller的pod不在这个node上,会走这个node的kube-proxy转发到Ingress Controller的pod上,多转发了一次。(例如:我们Ingress Controller的pod在192.168.2.142上,但是域名解析的是192.168.2.140上,这个时候192.168.2.140这个node上的kube-proxy会把请求转发到192.168.2.142上)。故建议使用daemonset+nodeSelector的方式来ingress controller的Pod负载(每个Node节点一个ingress controller的Pod),并在前端添加使用一个负载均衡器。

不创建nginx svc,效率最高(不使用nodeport的方式进行暴露)。如果我们使用Nodeport的方式,流量是NodeIP->svc->ingress-controller(pod)这样的话会多走一层svc层,不管svc层是使用iptables还是lvs都会降低效率。如果使用hostNetwork的方式就是直接走Node节点的主机网络,唯一要注意的是hostNetwork下pod会继承宿主机的网络协议,也就是使用了主机的dns,会导致svc的请求直接走宿主机的上到公网的dns服务器而非集群里的dns server,需要设置pod的dnsPolicy: ClusterFirstWithHostNet即可解决

Ingress Controller部署方式:

  • daemonSet + nodeSeletor (一个Node节点运行一个Ingress Controller的Pod,当有多个Node的时候可以使用污点或者通过指定nodeSelector来指定部分主机来运行Ingress Controller的Pod)
  • deploy的方式部署多个ingress controller:设置replicas数量(不能大于node节点数) + nodeSeletor / podantifinity

使用 daemonSet + nodeSeletor 方式部署
1)创建一个名为ingress-nginx的service
首先我们要创建一个ingress-nginx的svc不然ingress nginx的log里会一直刷找不到ingress-nginx的svc不处理的话会狂刷log导致机器load过高,所以先创建一个同名的svc即可解决,例如创建一个不带选择器clusterip为None的。

[root@k8s-m1 nginx-ingress]#  cat ingress-nginx-no-clusterip-service.yaml
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: ClusterIP
  clusterIP: "None"
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP

[root@k8s-m1 nginx-ingress]#  kubectl get svc -n ingress-nginx
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
ingress-nginx   ClusterIP   None         <none>        80/TCP,443/TCP   20s

2)修改ingress-controller mandatory.yaml文件

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      serviceAccountName: nginx-ingress-serviceaccount
·······

[root@k8s-m1 nginx-ingress]# kubectl apply -f  mandatory.yaml 

[root@k8s-m1 nginx-ingress]# kubectl get pod -n ingress-nginx  -o wide 
NAME                             READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
nginx-ingress-controller-92rws   1/1     Running   0          4m35s   192.168.2.141   k8s-m2   <none>           <none>
nginx-ingress-controller-ffbww   1/1     Running   0          4m35s   192.168.2.142   k8s-m3   <none>           <none>
nginx-ingress-controller-qtnbg   1/1     Running   0          4m35s   192.168.2.140   k8s-m1   <none>           <none>

说明:修改部署方式为DaemonSet以及删除replicas副本集参数,新增 hostNetwork: true 和 dnsPolicy: ClusterFirstWithHostNet参数。我们可以看到Pod的IP就直接是Node节点的IP。

3)使用负载均衡器
使用平台自带的负载均衡器或者自己搭建一个haproxy+keepalived(后面分享)

最后,不同版本之间略有不同,请根据大致思路选择适合自己的版本。

更多关于kubernetes的知识分享,请前往博客主页。编写过程中,难免出现差错,敬请指出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/756467.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ubuntu 不能检测到显卡信息

开始时&#xff1a;lspci | grep -i nvidia 01:00.0 VGA compatible controller: NVIDIA Corporation Device 2489 (rev a1) 01:00.1 Audio device: NVIDIA Corporation Device 228b (rev a1) 运行sudo update-pciids 运行 lspci | grep -i nvidia 找到显卡了

Linux - 进阶 NFS服务器搭建 详解实验操作

建立 NFS 服务器&#xff0c;使用客户端成功访问 # 搭建环境 server 为服务端&#xff0c; node1 为客户端 &#xff08; 客户端是通过 服务端克隆出来的机子&#xff0c;并改了 IP 和 主机名&#xff09; IP 都显示出&#xff0c;并且双方能够 Ping 通 这样准备环…

顶尖公司是平均水平的100倍,惊讶吗?

行业顶尖公司人员平均能力水平&#xff0c;在行业平均水平的100倍之上&#xff01; 程序员的超级榜样&#xff1a;美国integram公司13个人&#xff0c;最后被facebook用10亿美金收购 《中庸》人能一之己百之&#xff0c;人能十之己千之 趣讲大白话&#xff1a;百倍努力&#xf…

项目管理软件挑选诀窍:6个必须知道的关键点!

项目管理软件对于任何希望简化其操作和提高效率的组织来说都是一个有价值的工具。然而&#xff0c;市场上有这么多的选择&#xff0c;选择合适的软件可能是一项艰巨的任务。在本文中&#xff0c;我们将讨论如何选择满足您业务需求的项目管理软件。 1、确定你的挑战和限制 选择项…

TL5000可调谐激光器控制软件系统

画了两周时间&#xff0c;利用下班时间&#xff0c;设计了一个ITLA可调谐激光器控制系统&#xff0c;从硬件到软件。 这是使用的界面&#xff0c;实现了下面的功能&#xff1a; 1、模块信息的读取&#xff0c;包括生产日期&#xff0c;生产厂家&#xff0c;型号&#xff0c;序…

在WIN10系统中安装TIA博途V18,重启后提示安装介质不可用,请插入DVD 或检查网络连接的解决办法

在WIN10系统中安装TIA博途V18,重启后提示安装介质不可用,请插入DVD 或检查网络连接的解决办法 原因:下载的安装包为ISO文件,若没有解压缩,直接点击打开安装,则会出现这样的错误提示。 解决办法: 把安装包解压缩之后再进行安装。 安装教程可参考以下步骤: 前提条件: T…

【iOS内存管理-编译链接的过程】

文章目录 前言计算机语言文件后缀名 编译和链接的过程编译链接预处理&#xff08;预编译&#xff09;-> 产生.i文件编译 -> 产生.s文件汇编 -> 产生.o文件链接 总结 前言 就我而言&#xff0c;iOS开发的过程中接触到的编译链接方面的知识很少&#xff0c;这部分知识还…

【JavaSE】- 包装类和String常用方法

包装类和常用方法 1.1 包装类1.2 自动装箱和自动拆箱1.3 包装类型转String类型2.1 String2.2 String常用方法3.1 StringBuffer4.1 StringBuilder 1.1 包装类 1.2 自动装箱和自动拆箱 // 手动装箱int n1 100;Integer integer new Integer(n1);// 手动拆箱Integer integer02 I…

electron globalShortcut 快捷键与系统全局快捷键冲突

用 electron 开发自己的接口测试工具&#xff08;Post Tools&#xff09;&#xff0c;在设置了 globalShortcut 快捷键后&#xff0c;发现应用中的快捷键与系统全局快捷键冲突了&#xff0c;导致系统快捷键不可正常使用。 快捷键配置 export function initGlobalShortcut(main…

20款奔驰E300升级柏林之声音响系统,体验不一样的感觉

享有盛名的 Burmester 音响系统可带来独特音质&#xff0c;打造震撼的听觉体验。高性能扬声器可营造殿堂级的立体声音响效果。您可以分别为前排和后排乘客优化这一设置&#xff0c;进一步提升听觉体验。

如何快速搭建自己同城跑腿系统?尚无忧跑腿小程序源码

是一款集代买、代送、代取等服务为一体的本地同城跑腿配送系统&#xff0c;支持二次开发&#xff0c;功能定制。 跑腿系统可众包模式&#xff0c;提供全套解决方案&#xff0c;包括跑腿系统配送端、用户端以及强大的后台管理系统。 使用uniappthinkphp技术 适配支持公众号APP…

【问卷分析】调节效应检验的操作②

文章目录 2.2 当调节变量是分类变量时&#xff08;1&#xff09; 确定组别区分&#xff08;2&#xff09;检验调节效应值&#xff08;3&#xff09;结果解读 接上一篇文章&#xff1a; 【问卷分析】调节效应检验的操作① 2.2 当调节变量是分类变量时 我们将以该模型中的调节变…

ASO优化之在海外如何进行竞品分析

进行竞争对手研究&#xff0c;需要分析当前的市场形势&#xff0c;确定竞争对手表现的模式&#xff0c;并将其应用到我们应用营销策略中。不同的应用可以在直观的用户界面上进行简单的比较&#xff0c;很容易看到长期趋势。 在App Store和Google Play上获取竞争对手评论区的信…

promise规范及应用

##promise解析 *啥是异步? //异步执行let count 1let timer setTimeout(function () {countconsole.log(in, count);}, 1000);console.log(out);// out>1000>in//循环执行let count 1let timer setInterval(function () {countconsole.log(in, count);}, 1000);con…

YOLO学习笔记1. YOLOV1的基本概念

YOLO学习笔记1. YOLOV1的基本概念 一、 YOLO简介二、一些基本概念1. two-stage和one-stage2. 指标分析&#xff08;1&#xff09;精度的概念&#xff08;2&#xff09;召回率的概念&#xff08;3&#xff09;IOU&#xff08;4&#xff09;置信度阈值&#xff08;5&#xff09; …

成功解决VScode每次只能打开一个文件,即只能打开一个编辑窗口。

成功解决VScode每次只能打开一个文件&#xff0c;即只能打开一个编辑窗口。 解决方案 解决方案 点击文件 --> 首选项 --> 设置 --> 工作台 --> 编辑管理 --> 取消勾选Enable Preview 如下图所示&#xff1a; 下拉&#xff0c;取消勾选Enable Preview

[JVM] 1. 初步认识JVM

核心思想&#xff1a; “Write Once, Run anywhere”. 各种语言通过编译器转换成字节码文件&#xff0c;在JVM上运行。 一、Java虚拟机 Java虚拟机是一台执行Java字节码的虚拟计算机&#xff0c;它拥有独立的运行机制&#xff0c;其运行的Java字节码也未必由Java语言编译而成…

Netty核心技术十一--用Netty 自己 实现 dubbo RPC

1. RPC基本介绍 RPC&#xff08;Remote Procedure Call&#xff09;:远程 过程调用&#xff0c;是一个计算机 通信协议。该协议允许运 行于一台计算机的程序调 用另一台计算机的子程序&#xff0c; 而程序员无需额外地为这 个交互作用编程 两个或多个应用程序都分 布在不同的服…

AJAX与axios框架

文章目录 前言案例跨域访问总结❗ 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 通过 ajax 进行前后端交互 案例 此项目用到了javaweb知识 首先创建JavaWeb项目编写代码&#xff1a; package ajax;import java.io.IOException; import java.util.A…

个人引导页源码带三个按钮可添加

个人引导页源码带三个按钮可添加 简洁优雅引导页