千家信息网

docker中pod生命周期的示例分析

发表于:2025-01-17 作者:千家信息网编辑
千家信息网最后更新 2025年01月17日,这篇文章给大家分享的是有关docker中pod生命周期的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。查看资源配置清单帮助[root@master manifest
千家信息网最后更新 2025年01月17日docker中pod生命周期的示例分析

这篇文章给大家分享的是有关docker中pod生命周期的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

查看资源配置清单帮助

[root@master manifests]# kubectl explain pods.spec.containers #查看帮助

资源配置清单分类

自主式pod资源:

资源的清单格式:

一级字段:apiVersion(group/version组成),kind,metadata(包括name,namespace,labels,annotations),spec ,status。

pod资源-spec.containers

- name:pod名字

image:镜像名字

imagePullPolicy:表示从哪拉镜像,Always(不管本地有没有镜像,都要从仓库中下载镜像,也就是说,即使本地有镜像了,也不使用本地镜像,而是从仓库下载), Never(从来不从仓库下载镜像,也就是说本地有镜像就用,没有就算了), IfNotPresent(如果本地存在就直接使用,不存在才从仓库下载)。默认的策略是:当镜像标签版本是latest,默认策略就是Always;如果指定特定版本默认拉取策略就是IfNotPresent。


如上图,指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,这样每次启动容器,也不会从仓库重新下载镜像了。

ports:指定暴露容器端口号,可以指定多个端口,如下:

[root@master manifests]# cat pod-demo.yaml apiVersion: v1kind: Podmetadata:  name: pod-demo  namespace: default  labels:    app: myapp  #kv格式的,也可以用花括号表示    tier: frontend #定义所属的层次spec:  containers:   - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示    image: tomcat     ports:    - name: http      containerPort: 80    - name: https      containerPort: 443  - name: busybox    image: busybox:latest    imagePullPolicy: IfNotPresent #指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,以后每次启动容器,也不会从仓库重新下载镜像了    command:    - "/bin/sh"    - "-c"    - "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"   #以上命令也可以写作:command: ["/bin/sh","-c","sleep 3600"]

args:相当于dockerfile里面的cmd

command:相当于docker里面的Entrypoint

如果既没有指定args,也没有指定command,那么会默认使用dockfile的cmd和entrypoint。

如果指定了command,但没有提供args,那么就直接运行command。

如果指定了args,但是没指定command,那么将使用镜像中的entrypoint命令,把我们写的args当做参数传递给镜像中的entrypoint。

如果既用来command,又用了args,那么镜像中的cmd和entrypoint将被忽略,而使用K8s提供的command with args。

参考文档:https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/

标签

标签是k8s极具特色的管理方式。一个标签可以对应多个资源,一个资源也可以有多个标签,它们是多对多的关系。

一个资源拥有多个标签,可以实现不同维度的管理。

标签是key=value格式的,key最大63个字符,只能是字母、数字、_、-、.五种类型的组合。只能以字母或数字开头结尾。

我们也可以使用标签选择器来指定能使用哪些标签。

可以使用如下命令看标签:

[root@master manifests]# kubectl get pods --show-labelsNAME                          READY     STATUS             RESTARTS   AGE       LABELSpod-demo                      1/2       CrashLoopBackOff   24         1h        app=myapp,tier=frontend

可以用-l来过滤包含app标签的pod

[root@master manifests]# kubectl get pods -l app --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   25         1h        app=myapp,tier=frontend

给资源对象打标签,我们再给前面创建的pod-demo pod打个release=canary的标签:

[root@master manifests]# kubectl label pods pod-demo release=canarypod/pod-demo labeled
[root@master manifests]# kubectl get pods -l app --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   27         1h        app=myapp,release=canary,tier=frontend

修改标签的值:

[root@master manifests]# kubectl label pods pod-demo release=stable --overwritepod/pod-demo labeled
[root@master manifests]# kubectl get pods -l app --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   27         1h        app=myapp,release=stable,tier=frontend

查找既有release标签,又拥有app标签的:

[root@master manifests]# kubectl get pods -l app,release --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   27         2h        app=myapp,release=stable,tier=frontend

标签选择器分为:等值关系的标签选择器和集合关系的标签选择器。

等值关系的标签选择器:可以用=或者==表示等于,!=表示不等于:

[root@master manifests]# kubectl get pods -l release=stable --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   29         2h        app=myapp,release=stable,tier=frontend
[root@master manifests]# kubectl get pods -l release=stable,app=myapp --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   30         2h        app=myapp,release=stable,tier=frontend
[root@master manifests]# kubectl get pods -l release!=stable --show-labelsNAME                          READY     STATUS             RESTARTS   AGE       LABELSclient                        1/1       Running            0          1d        run=clientmyapp-fcc5f7f7c-4x2p7         0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myappmyapp-fcc5f7f7c-dnkdq         0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myappmytomcat-5f8c6fdcb-7t5s2      1/1       Running            0          1d        pod-template-hash=194729876,run=mytomcatmytomcat-5f8c6fdcb-lhcsc      1/1       Running            0          1d        pod-template-hash=194729876,run=mytomcatmytomcat-5f8c6fdcb-rntrg      1/1       Running            0          1d        pod-template-hash=194729876,run=mytomcatnginx-deploy-5b595999-fpm8x   1/1       Running            0          1d        pod-template-hash=16151555,release=canary,run=nginx-deploy

集合关系的标签选择器:key in (value1,value2...),key notin (value1,value2...),!key

[root@master ~]# kubectl get pods -l "release in (canary,beta,alpha)" --show-labelsNAME                          READY     STATUS    RESTARTS   AGE       LABELSnginx-deploy-5b595999-fpm8x   1/1       Running   0          1d        pod-template-hash=16151555,release=canary,run=nginx-deploy
[root@master ~]# kubectl get pods -l "release notin (canary,beta,alpha)" --show-labelsNAME                       READY     STATUS             RESTARTS   AGE       LABELSclient                     1/1       Running            0          1d        run=clientmyapp-fcc5f7f7c-4x2p7      0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myappmyapp-fcc5f7f7c-dnkdq      0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myapp

我们知道pod控制器和service都是要通过标签来进行关联,通常使用matchLabels,matchExpressions。许多资源支持内嵌字段定义其使用的标签选择器。

matchLabels:直接给定键值,相当于使用等值关系一样;

matchExpressions:基于给定的表达式来定义使用标签选择器,格式为{key!"KEY",operator:"OPERATOR",values:[VAL1,VAL2,....]},常用的操作符有:

1)In,NotIn,:values字段的值必须为非空列表

2)Exists,NotExists:values字段的值必须为空列表

不光pods有标签,nodes等对象都有标签,如下:

[root@master ~]# kubectl get nodes --show-labelsNAME      STATUS    ROLES     AGE       VERSION   LABELSmaster    Ready     master    4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=node1     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node1node2     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node2

上面的标签是内建的标签,其中beta.kubernetes.io这部分是能在dns中解析的,该部分字符长度不能超过253个字符。

同样,我们也可以给nodes打标签,比如我们下面给node1节点打个disktype=ssd的标签

[root@master ~]# kubectl label nodes node1 disktype=ssdnode/node1 labeled
[root@master ~]# kubectl get nodes --show-labelsNAME      STATUS    ROLES     AGE       VERSION   LABELSmaster    Ready     master    4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=node1     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=node1node2     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node2

节点选择器-nodeSelector和nodeName

nodeSelector:可以使pod运行在指定的node节点上,我们如下举例演示该功能。

[root@master ~]# kubectl get pods -o wideNAME                          READY     STATUS             RESTARTS   AGE       IP            NODEclient                        1/1       Running            0          2d        10.244.2.4    node2myapp-fcc5f7f7c-4x2p7         0/1       ImagePullBackOff   0          1d        10.244.1.9    node1myapp-fcc5f7f7c-dnkdq         0/1       ImagePullBackOff   0          1d        10.244.2.6    node2mytomcat-5f8c6fdcb-7t5s2      1/1       Running            0          1d        10.244.2.8    node2mytomcat-5f8c6fdcb-lhcsc      1/1       Running            0          1d        10.244.2.7    node2mytomcat-5f8c6fdcb-rntrg      1/1       Running            0          1d        10.244.1.10   node1nginx-deploy-5b595999-fpm8x   1/1       Running            0          1d        10.244.1.7    node1pod-demo                      1/2       CrashLoopBackOff   303        1d        10.244.2.11   node2

上面我们看到pod-demo运行在node2节点上,下面我们让它运行在node1节点上。我们刚才在node1上打了个disktype=ssd的标签,所以我们用nodeSelector在资源清单中如下定义:

[root@master manifests]# cat pod-demo.yaml apiVersion: v1kind: Podmetadata:  name: pod-demo  namespace: default  labels:    app: myapp  #kv格式的,也可以用花括号表示    tier: frontend #定义所属的层次spec:  containers:   - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示    image: tomcat     ports:    - name: http      containerPort: 80    - name: https      containerPort: 443  - name: busybox    image: busybox:latest    imagePullPolicy: IfNotPresent #指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,以后每次启动容器,也不会从仓库重新下载镜像了    command:    - "/bin/sh"    - "-c"    - "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"   #以上命令也可以写作:command: ["/bin/sh","-c","sleep 3600"]  nodeSelector: #指定该pod运行在有disktype=ssd标签的node节点上    disktype: ssd
[root@master manifests]# kubectl delete -f pod-demo.yaml pod "pod-demo" deleted
[root@master manifests]# kubectl create  -f pod-demo.yaml pod/pod-demo created
[root@master manifests]# kubectl get pods -o wideNAME                          READY     STATUS             RESTARTS   AGE       IP            NODEclient                        1/1       Running            0          2d        10.244.2.4    node2myapp-fcc5f7f7c-4x2p7         0/1       ImagePullBackOff   0          1d        10.244.1.9    node1myapp-fcc5f7f7c-dnkdq         0/1       ImagePullBackOff   0          1d        10.244.2.6    node2mytomcat-5f8c6fdcb-7t5s2      1/1       Running            0          1d        10.244.2.8    node2mytomcat-5f8c6fdcb-lhcsc      1/1       Running            0          1d        10.244.2.7    node2mytomcat-5f8c6fdcb-rntrg      1/1       Running            0          1d        10.244.1.10   node1nginx-deploy-5b595999-fpm8x   1/1       Running            0          1d        10.244.1.7    node1pod-demo                      2/2       Running            2          37s       10.244.1.14   node1

上面看到,pod-demo运行在了带有disktype=ssd标签的node1节点上了。

那么有人可能会问了,我们可不可以指定pod-demo运行在指定node上呢。当然可以了,这个选项就是nodeName。大家可以自定去测试。

资源注解annotations

与labels的区别是,annotaitons不能用于挑选资源对象,仅用于为对象提供原数据。这些元数据可能被某些程序所用到,而且很重要。annotations的键值对没有字符数限制。

查看资源的注解:

[root@master manifests]# kubectl delete -f pod-demo.yaml pod "pod-demo" deleted
[root@master manifests]# cat cat pod-demo.yaml cat: cat: No such file or directoryapiVersion: v1kind: Podmetadata:  name: pod-demo  namespace: default  labels:    app: myapp  #kv格式的,也可以用花括号表示    tier: frontend #定义所属的层次  annotations:    chenzx.com/created-by: "cluster-admin" #这是注解的键值对spec:  containers:   - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示    image: tomcat     ports:    - name: http      containerPort: 80    - name: https      containerPort: 443  - name: busybox    image: busybox:latest    imagePullPolicy: IfNotPresent #指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,以后每次启动容器,也不会从仓库重新下载镜像了    command:    - "/bin/sh"    - "-c"    - "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"   #以上命令也可以写作:command: ["/bin/sh","-c","sleep 3600"]  nodeSelector: #指定该pod运行在有disktype=ssd标签的node节点上    disktype: ssd
[root@master manifests]# kubectl create -f pod-demo.yaml pod/pod-demo created
[root@master manifests]# kubectl describe pods pod-demoAnnotations:        chenzx.com/created-by=cluster-adminStatus:             RunningIP:                 10.244.1.15

pod的生命周期

一个容器里面可以运行多个进程,但是通常我们只在容器里面运行一个进程。

在一个pod中,可以运行多个容器,但是通常我们只在一个pod里面运行一个容器。

一个容器在创建之前,有多个初始化容器(init container)用来进行初始化环境,init container执行完,它就退出了。接下来是主容器(main container)开始启动,主容器启动时也要初始化主容器里面的环境。在主容器刚刚启动之后,用户可以手动嵌入做一个操作叫post start。在主容器结束前,也可以做一个收尾操作pre stop,用来在主容器结束前做一个清理。

在post start后,就开始做健康检查,第一个健康检查叫存活状态检查(liveness probe ),用来检查主容器存活状态的;第二个健康检查叫准备就绪检查(readyness probe),用来检查主容器是否启动就绪。

pod的状态有:

a) Pending:当启动一个容器时,发现条件不满足,就会进入pending状态;

b) Runing

c)Failed

d)Succeeded

e) Unknown;如果kubelete出现故障,那么apiserver就连不上kubelete了,就会出现未知的错误

创建pod的过程:pod创建时先和apiserver沟通,然后把信息存储在etcd中;接下来apiserver会请求scheduler,并把调度的结果也保存在etcd中。假如scheduler把pod调度到node1节点上了,此时node1节点上的kublete会从etcd中拿到用户创建的清单,根据清单在node1上运行这个pod。不管pod在node1上运行成功还是失败,都会把结果反馈给apiserver,同时把运行结果保存在etcd中。

健康检查分三个层次:1、直接执行命令;2、向tcp连接请求;3、向http发get请求。

总结:pod生命周期中的重要行为:

1)初始化容器

2)容器探测(liveness存活行探测和readness准备就绪探测)

livenessProbe(存活状态探测)

 存活不一定就绪。
[root@master manifests]# kubectl explain pods.spec.containers.livenessProbe

可以看到有三种探针,exec、 httpGet、tcpSocket

failureThreshold表示探测失败次数,默认是3探测次失败,才认为是真失败了。

periodSeconds:周期间隔时长,默认10s探测一次;

timeoutSeconds:超时时间,表示发出探测,对方始终没有响应,需要等多久,默认等1s

initialDelaySeconds:默认是容器一启动就开始探测,但是此时容器可能还没启动完呢,所以这时探测肯定是失败的。所以initialDelaySeconds表示容器启动多长时间后才开始探测。

[root@master manifests]# kubectl explain pods.spec.containers.livenessProbe.exec
[root@master manifests]# cat liveness.exec.ymal apiVersion: v1kind: Podmetadata:  name: liveness-exec-pod  namespace: defaultspec:  containers:  - name: liveness-exec-container    image: busybox:latest    imagePullPolicy: IfNotPresent #如果存在就不要下载了    command: ["/bin/sh","-c","touch /tmp/healthy;sleep 60;rm -f /tmp/healthy;sleep 3600"]    livenessProbe: #存活性探测      exec:         command: ["test","-e","/tmp/healthy"] #-e表示探测文件是否存在      initialDelaySeconds: 1 #表示容器启动后多长时间开始探测      periodSeconds: 3 #表示每隔3s钟探测一次
[root@master manifests]# kubectl create -f liveness.exec.ymal pod/liveness-exec-pod created
[root@master manifests]# kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEliveness-exec-pod             1/1       Running            2          4m
[root@master manifests]# kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEliveness-exec-pod             1/1       Running            4          6m
[root@master manifests]# kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEclient                        1/1       Running            0          3dliveness-exec-pod             1/1       Running            5          9m
[root@master manifests]#  kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEclient                        1/1       Running            0          3dliveness-exec-pod             1/1       Running            9          23m

可以看到restart此时在随着时间增长。

上面的例子是用exec执行命令进行探测的。

下面我们看看基于tcp和httpget探测的选项。

[root@master manifests]kubectl explain pods.spec.containers.livenessProbe.tcpSocket
[root@master manifests]# kubectl explain pods.spec.containers.livenessProbe.httpGet

下面举个例子:

[root@master manifests]# cat liveness.httpget.yaml apiVersion: v1kind: Podmetadata:  name: liveness-httpget-pod  namespace: defaultspec:  containers:  - name: liveness-httpget-container    image: nginx:latest    imagePullPolicy: IfNotPresent #如果存在就不要下载了    ports:    - name: http      containerPort: 80    livenessProbe: #存活性探测      httpGet:        port: http        path: /index.html      initialDelaySeconds: 1      periodSeconds: 3 #表示每隔3s钟探测一次
[root@master manifests]# kubectl  create -f liveness.httpget.yaml
[root@master manifests]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEliveness-httpget-pod          1/1       Running            0          4m
[root@master manifests]# kubectl exec -it liveness-httpget-pod  -- /bin/sh# rm -rf  /usr/share/nginx/html/index.html
[root@master manifests]#  kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEliveness-httpget-pod          1/1       Running            1          27m

上面可以看到,当删除pod里面的/usr/share/nginx/html/index.html,liveness监测到index.html文件被删除了,所以restarts次数为1,但是只重启一次,不会再重启了。这是因为重启一次后,nginx容器就重新初始化了,里面就会又生成index.html文件。所以里面就会有新的index.html文件了。

readlinessProbe(准备就绪型探针)

[root@master manifests]# cat  readiness-httpget.ymal apiVersion: v1kind: Podmetadata:  name: readdliness-httpget-pod  namespace: defaultspec:  containers:  - name: readliness-httpget-container    image: nginx:latest    imagePullPolicy: IfNotPresent #如果存在就不要下载了    ports:    - name: http      containerPort: 80    readinessProbe: #准备型探针      httpGet:        port: http        path: /index.html      initialDelaySeconds: 1      periodSeconds: 3 #表示每隔3s钟探测一次
[root@master manifests]# kubectl create -f readiness-httpget.ymal pod/readdliness-httpget-pod created
[root@master ~]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEreaddliness-httpget-pod       1/1       Running            0          16h
[root@master ~]# kubectl exec -it readdliness-httpget-pod -- /bin/sh# rm -rf /usr/share/nginx/html/index.html
[root@master ~]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEreaddliness-httpget-pod       0/1       Running            0          16h

上面可以看到,ready变成0/1了,但是status是runing的,这就是说nginx进程是在的,只是index.html不见了,可以判定nginx没有就绪。

postStart(启动后钩子)

[root@master ~]# kubectl  explain pods.spec.containers.lifecycle.postStart

postStart是指容器在启动之后立即执行的操作,如果执行操作失败了,容器将被终止并且重启。而重启与否是由重启策略。

[root@master manifests]# cat poststart-pod.yaml apiVersion: v1kind: Podmetadata:  name: poststart-pod  namespace: defaultspec:  containers:  - name: busybox-httpd    image: busybox:latest    imagePullPolicy: IfNotPresent    lifecycle: #生命周期事件      postStart:        exec:          command: ["mkdir", "-p","/data/web/html"] #这个command是定义postStart后的需要执行的命令    command: ["/bin/sh","-c","sleep 3600"] #这是定义容器里面执行的命令,不过这个命令要先于postStart里面的command    #args: ["-f","-h /data/web/html"]  #-f是前台,-h是家目录
[root@master manifests]# kubectl create -f poststart-pod.yaml pod/posttart-pod created

说明:删除的方法

[root@master manifests]# kubectl delete -f poststart-pod.yaml pod "posttart-pod" deleted
[root@master manifests]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEpoststart-pod                 1/1       Running            0          3m
[root@master manifests]#  kubectl exec -it poststart-pod -- /bin/sh/ # ls /dataweb/ # ls /data/web/html/

上面看到在容器启动后,建立了/data/web/html目录。这就是postStart的用法。

preStop(终止之前钩子)

[root@master ~]# kubectl  explain pods.spec.containers.lifecycle.preStop

preStop是指容器在终止前要立即执行的命令,等这些命令执行完了,容器才能终止。

容器的重启策略-restartPolicy

一旦pod中的容器挂了,我们就把容器重启。

策略包括如下:

Always:表示容器挂了总是重启,这是默认策略

OnFailures:表容器状态为错误时才重启,也就是容器正常终止时才重启

Never:表示容器挂了不予重启

对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推

容器的终止策略

k8s会给容器30s的时间进行终止,如果30s后还没终止,就会强制终止。

总结

pod:        apiVersion        kind        metadata        spec        status(只读)        spec:                containers                nodeSelector                nodeName                restartPolicy: Always,Never,OnFailure                containers:                        name                        image                        imagePullPolicy: Always、Never、IfNotPresent                        ports:                                name                                containerPort                        livenessProbe                        readinessProbe                        liftcycle                ExecAction: exec                TCPSocketAction: tcpSocket                HTTPGetAction: httpGet

感谢各位的阅读!关于"docker中pod生命周期的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

容器 标签 探测 镜像 资源 运行 命令 策略 节点 格式 选择 仓库 多个 这是 检查 周期 清单 版本 状态 生命 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 重庆计算机软件开发哪家可靠 上海播呗网络技术有限公司 2022免费服务器节点 网页搭建服务器搭建 倩女幽魂手游天下会服务器怎么找 网络安全本科毕业工资 清除服务器的安全证书 奉贤区优势网络安全创新服务 简述车载网络技术发展趋势 币圈跟单软件开发 软件开发项目甲方实施流程 长沙云服务器网吧 软件开发电话销售好做吗 做程序员好还是网络安全 软件开发 bug管理 香港线下生鲜配送软件开发 达梦数据库查询数据库名称 lol国外怎么查数据库 超激斗梦境无法连接到服务器1 河南服务器带宽是什么意思 网络安全法第56条 警察用的网络技术手段 一个域有且只有一个主域名服务器 机务段网络安全与信息化 软件开发画图师 关注网络安全宣传标语 我的世界已经开服的服务器地址 蓝桥云课MySQL数据库实验 网络安全画 一等奖小视频 铜仁web服务器供应商
0