k8sday02

第四章 实战入门

本章节将介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其进行访问。

Namespace

​ Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离

​ 默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。

​ 可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。

kubernetes在集群启动之后,会默认创建几个namespace

[root@master ~]# kubectl  get namespace
NAME              STATUS   AGE
default           Active   45h     #  所有未指定Namespace的对象都会被分配在default命名空间
kube-node-lease   Active   45h     #  集群节点之间的心跳维护,v1.13开始引入
kube-public       Active   45h     #  此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system       Active   45h     #  所有由Kubernetes系统创建的资源都处于这个命名空间

下面来看namespace资源的具体操作:

查看

# 1 查看所有的ns  命令:kubectl get ns
[root@master ~]# kubectl get ns
NAME              STATUS   AGE
default           Active   45h
kube-node-lease   Active   45h
kube-public       Active   45h     
kube-system       Active   45h     

# 2 查看指定的ns   命令:kubectl get ns ns名称
[root@master ~]# kubectl get ns default
NAME      STATUS   AGE
default   Active   45h

# 3 指定输出格式  命令:kubectl get ns ns名称  -o 格式参数
# kubernetes支持的格式有很多,比较常见的是wide、json、yaml
[root@master ~]# kubectl get ns default -o yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: "2020-04-05T04:44:16Z"
  name: default
  resourceVersion: "151"
  selfLink: /api/v1/namespaces/default
  uid: 7405f73a-e486-43d4-9db6-145f1409f090
spec:
  finalizers:
  - kubernetes
status:
  phase: Active
  
# 4 查看ns详情  命令:kubectl describe ns ns名称
[root@master ~]# kubectl describe ns default
Name:         default
Labels:       
Annotations:  
Status:       Active  # Active 命名空间正在使用中  Terminating 正在删除命名空间

# ResourceQuota 针对namespace做的资源限制
# LimitRange针对namespace中的每个组件做的资源限制
No resource quota.
No LimitRange resource.

创建

# 创建namespace
[root@master ~]# kubectl create ns dev
namespace/dev created

删除

# 删除namespace
[root@master ~]# kubectl delete ns dev
namespace "dev" deleted

配置方式

首先准备一个yaml文件:ns-dev.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: dev

然后就可以执行对应的创建和删除命令了:

​ 创建:kubectl create -f ns-dev.yaml

​ 删除:kubectl delete -f ns-dev.yaml

Pod

Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中。

Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。

kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。可以通过下面命令查看:

[root@master ~]# kubectl get pod -n kube-system
NAMESPACE     NAME                             READY   STATUS    RESTARTS   AGE
kube-system   coredns-6955765f44-68g6v         1/1     Running   0          2d1h
kube-system   coredns-6955765f44-cs5r8         1/1     Running   0          2d1h
kube-system   etcd-master                      1/1     Running   0          2d1h
kube-system   kube-apiserver-master            1/1     Running   0          2d1h
kube-system   kube-controller-manager-master   1/1     Running   0          2d1h
kube-system   kube-flannel-ds-amd64-47r25      1/1     Running   0          2d1h
kube-system   kube-flannel-ds-amd64-ls5lh      1/1     Running   0          2d1h
kube-system   kube-proxy-685tk                 1/1     Running   0          2d1h
kube-system   kube-proxy-87spt                 1/1     Running   0          2d1h
kube-system   kube-scheduler-master            1/1     Running   0          2d1h

创建并运行

kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的

# 命令格式: kubectl run (pod控制器名称) [参数] 
# --image  指定Pod的镜像
# --port   指定端口
# --namespace  指定namespace
[root@master ~]# kubectl run nginx --image=nginx:1.17.1 --port=80 --namespace dev 
deployment.apps/nginx created

查看pod信息

# 查看Pod基本信息
[root@master ~]# kubectl get pods -n dev
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5ff7956ff6-fg2db   1/1     Running   0          43s

# 查看Pod的详细信息
[root@master ~]# kubectl describe pod nginx-5ff7956ff6-fg2db -n dev
Name:         nginx-5ff7956ff6-fg2db
Namespace:    dev
Priority:     0
Node:         node1/192.168.109.101
Start Time:   Wed, 08 Apr 2020 09:29:24 +0800
Labels:       pod-template-hash=5ff7956ff6
              run=nginx
Annotations:  
Status:       Running
IP:           10.244.1.23
IPs:
  IP:           10.244.1.23
Controlled By:  ReplicaSet/nginx-5ff7956ff6
Containers:
  nginx:
    Container ID:   docker://4c62b8c0648d2512380f4ffa5da2c99d16e05634979973449c98e9b829f6253c
    Image:          nginx:1.17.1
    Image ID:       docker-pullable://nginx@sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 08 Apr 2020 09:30:01 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-hwvvw (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-hwvvw:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-hwvvw
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled    default-scheduler  Successfully assigned dev/nginx-5ff7956ff6-fg2db to node1
  Normal  Pulling    4m11s      kubelet, node1     Pulling image "nginx:1.17.1"
  Normal  Pulled     3m36s      kubelet, node1     Successfully pulled image "nginx:1.17.1"
  Normal  Created    3m36s      kubelet, node1     Created container nginx
  Normal  Started    3m36s      kubelet, node1     Started container nginx

访问Pod

# 获取podIP
[root@master ~]# kubectl get pods -n dev -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP             NODE    ... 
nginx-5ff7956ff6-fg2db   1/1     Running   0          190s   10.244.1.23   node1   ...

#访问POD
[root@master ~]# curl http://10.244.1.23:80
<!DOCTYPE html>


	Welcome to nginx!<<span class="token operator">/</span>title>
<<span class="token operator">/</span>head>
<body>
	<p><em>Thank you <span class="token keyword">for</span> <span class="token keyword">using</span> nginx<span class="token punctuation">.</span><<span class="token operator">/</span>em><<span class="token operator">/</span>p>
<<span class="token operator">/</span>body>
<<span class="token operator">/</span>html>
</code></pre> 
  <p><strong>删除指定Pod</strong></p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 删除指定Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete pod nginx-5ff7956ff6-fg2db -n dev</span>
pod <span class="token string">"nginx-5ff7956ff6-fg2db"</span> deleted

<span class="token comment"># 此时,显示删除Pod成功,但是再查询,发现又新产生了一个 </span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev</span>
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5ff7956ff6-jj4ng   1/1     Running   0          21s

<span class="token comment"># 这是因为当前Pod是由Pod控制器创建的,控制器会监控Pod状况,一旦发现Pod死亡,会立即重建</span>
<span class="token comment"># 此时要想删除Pod,必须删除Pod控制器</span>

<span class="token comment"># 先来查询一下当前namespace下的Pod控制器</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get deploy -n  dev</span>
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           9m7s

<span class="token comment"># 接下来,删除此PodPod控制器</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete deploy nginx -n dev</span>
deployment<span class="token punctuation">.</span>apps <span class="token string">"nginx"</span> deleted

<span class="token comment"># 稍等片刻,再查询Pod,发现Pod被删除了</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev</span>
No resources found in dev namespace<span class="token punctuation">.</span>
</code></pre> 
  <p><strong>配置操作</strong></p> 
  <p>创建一个pod-nginx.yaml,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">name</span><span class="token punctuation">:</span> pod
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
      <span class="token key atrule">protocol</span><span class="token punctuation">:</span> TCP
</code></pre> 
  <p>然后就可以执行对应的创建和删除命令了:</p> 
  <p>​ 创建:kubectl create -f pod-nginx.yaml</p> 
  <p>​ 删除:kubectl delete -f pod-nginx.yaml</p> 
  <h2>Label</h2> 
  <p>Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。</p> 
  <p>Label的特点:</p> 
  <ul> 
   <li>一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等</li> 
   <li>一个资源对象可以定义任意数量的Label ,同一个Label也可以被添加到任意数量的资源对象上去</li> 
   <li>Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除</li> 
  </ul> 
  <p>可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。</p> 
  <blockquote> 
   <p>一些常用的Label 示例如下:</p> 
   <ul> 
    <li>版本标签:“version”:“release”, “version”:“stable”…</li> 
    <li>环境标签:“environment”:“dev”,“environment”:“test”,“environment”:“pro”</li> 
    <li>架构标签:“tier”:“frontend”,“tier”:“backend”</li> 
   </ul> 
  </blockquote> 
  <p>标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:</p> 
  <p>​ Label用于给某个资源对象定义标识</p> 
  <p>​ Label Selector用于查询和筛选拥有某些标签的资源对象</p> 
  <p>当前有两种Label Selector:</p> 
  <ul> 
   <li> <p>基于等式的Label Selector</p> <p>name = slave: 选择所有包含Label中key="name"且value="slave"的对象</p> <p>env != production: 选择所有包括Label中的key="env"且value不等于"production"的对象</p> </li> 
   <li> <p>基于集合的Label Selector</p> <p>name in (master, slave): 选择所有包含Label中的key="name"且value="master"或"slave"的对象</p> <p>name not in (frontend): 选择所有包含Label中的key="name"且value不等于"frontend"的对象</p> </li> 
  </ul> 
  <p>标签的选择条件可以使用多个,此时将多个Label Selector进行组合,使用逗号","进行分隔即可。例如:</p> 
  <p>​ name=slave,env!=production</p> 
  <p>​ name not in (frontend),env!=production</p> 
  <p><strong>命令方式</strong></p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 为pod资源打标签</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl label pod nginx-pod version=1.0 -n dev</span>
pod/nginx-pod labeled

<span class="token comment"># 为pod资源更新标签</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl label pod nginx-pod version=2.0 -n dev --overwrite</span>
pod/nginx-pod labeled

<span class="token comment"># 查看标签</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod nginx-pod  -n dev --show-labels</span>
NAME        READY   STATUS    RESTARTS   AGE   LABELS
nginx-pod   1/1     Running   0          10m   version=2<span class="token punctuation">.</span>0

<span class="token comment"># 筛选标签</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod -n dev -l version=2.0  --show-labels</span>
NAME        READY   STATUS    RESTARTS   AGE   LABELS
nginx-pod   1/1     Running   0          17m   version=2<span class="token punctuation">.</span>0
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod -n dev -l version!=2.0 --show-labels</span>
No resources found in dev namespace<span class="token punctuation">.</span>

<span class="token comment">#删除标签</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl label pod nginx-pod version- -n dev</span>
pod/nginx-pod labeled
</code></pre> 
  <p><strong>配置方式</strong></p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
  <span class="token key atrule">labels</span><span class="token punctuation">:</span>
    <span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">"3.0"</span> 
    <span class="token key atrule">env</span><span class="token punctuation">:</span> <span class="token string">"test"</span>
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">name</span><span class="token punctuation">:</span> pod
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
      <span class="token key atrule">protocol</span><span class="token punctuation">:</span> TCP
</code></pre> 
  <p>然后就可以执行对应的更新命令了:kubectl apply -f pod-nginx.yaml</p> 
  <h2>Deployment</h2> 
  <p>​ 在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。</p> 
  <p>​ 在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment。</p>  
  <p><strong>命令操作</strong></p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 命令格式: kubectl run deployment名称  [参数] </span>
<span class="token comment"># --image  指定pod的镜像</span>
<span class="token comment"># --port   指定端口</span>
<span class="token comment"># --replicas  指定创建pod数量</span>
<span class="token comment"># --namespace  指定namespace</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl run nginx --image=nginx:1.17.1 --port=80 --replicas=3 -n dev</span>
deployment<span class="token punctuation">.</span>apps/nginx created

<span class="token comment"># 查看创建的Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev</span>
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5ff7956ff6-6k8cb   1/1     Running   0          19s
nginx-5ff7956ff6-jxfjt   1/1     Running   0          19s
nginx-5ff7956ff6-v6jqw   1/1     Running   0          19s

<span class="token comment"># 查看deployment的信息</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get deploy -n dev</span>
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   3/3     3            3           2m42s

<span class="token comment"># UP-TO-DATE:成功升级的副本数量</span>
<span class="token comment"># AVAILABLE:可用副本的数量</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get deploy -n dev -o wide</span>
NAME    READY UP-TO-DATE  AVAILABLE   AGE     CONTAINERS   IMAGES              SELECTOR
nginx   3/3     3         3           2m51s   nginx        nginx:1<span class="token punctuation">.</span>17<span class="token punctuation">.</span>1        run=nginx

<span class="token comment"># 查看deployment的详细信息</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe deploy nginx -n dev</span>
Name:                   nginx
Namespace:              dev
CreationTimestamp:      Wed<span class="token punctuation">,</span> 08 Apr 2020 11:14:14 <span class="token operator">+</span>0800
Labels:                 run=nginx
Annotations:            deployment<span class="token punctuation">.</span>kubernetes<span class="token punctuation">.</span>io/revision: 1
Selector:               run=nginx
Replicas:               3 desired <span class="token punctuation">|</span> 3 updated <span class="token punctuation">|</span> 3 total <span class="token punctuation">|</span> 3 available <span class="token punctuation">|</span> 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable<span class="token punctuation">,</span> 25% max surge
Pod Template:
  Labels:  run=nginx
  Containers:
   nginx:
    Image:        nginx:1<span class="token punctuation">.</span>17<span class="token punctuation">.</span>1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  <span class="token function">Type</span>           Status  Reason
  <span class="token operator">--</span><span class="token operator">--</span>           <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>  <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-5ff7956ff6 <span class="token punctuation">(</span>3/3 replicas created<span class="token punctuation">)</span>
Events:
  <span class="token function">Type</span>    Reason             Age    <span class="token keyword">From</span>                   Message
  <span class="token operator">--</span><span class="token operator">--</span>    <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>             <span class="token operator">--</span><span class="token operator">--</span>   <span class="token operator">--</span><span class="token operator">--</span>                   <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>
  Normal  ScalingReplicaSet  5m43s  deployment-controller  Scaled up replicaset nginx-5ff7956ff6 to 3
  
<span class="token comment"># 删除 </span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete deploy nginx -n dev</span>
deployment<span class="token punctuation">.</span>apps <span class="token string">"nginx"</span> deleted
</code></pre> 
  <p><strong>配置操作</strong></p> 
  <p>创建一个deploy-nginx.yaml,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> apps/v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Deployment
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">replicas</span><span class="token punctuation">:</span> <span class="token number">3</span>
  <span class="token key atrule">selector</span><span class="token punctuation">:</span>
    <span class="token key atrule">matchLabels</span><span class="token punctuation">:</span>
      <span class="token key atrule">run</span><span class="token punctuation">:</span> nginx
  <span class="token key atrule">template</span><span class="token punctuation">:</span>
    <span class="token key atrule">metadata</span><span class="token punctuation">:</span>
      <span class="token key atrule">labels</span><span class="token punctuation">:</span>
        <span class="token key atrule">run</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">spec</span><span class="token punctuation">:</span>
      <span class="token key atrule">containers</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
        <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
        <span class="token key atrule">ports</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
          <span class="token key atrule">protocol</span><span class="token punctuation">:</span> TCP
</code></pre> 
  <p>然后就可以执行对应的创建和删除命令了:</p> 
  <p>​ 创建:kubectl create -f deploy-nginx.yaml</p> 
  <p>​ 删除:kubectl delete -f deploy-nginx.yaml</p> 
  <h2>Service</h2> 
  <p>通过上节课的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。</p> 
  <p>虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:</p> 
  <ul> 
   <li>Pod IP 会随着Pod的重建产生变化</li> 
   <li>Pod IP 仅仅是集群内可见的虚拟IP,外部无法访问</li> 
  </ul> 
  <p>这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。</p> 
  <p>Service可以看作是一组同类Pod<strong>对外的访问接口</strong>。借助Service,应用可以方便地实现服务发现和负载均衡。</p> 
  <p>[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XPCTj7gi-1691505645135)(assets/image-20200408194716912.png)]</p> 
  <p><strong>操作一:创建集群内部可访问的Service</strong></p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 暴露Service</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev</span>
service/svc-nginx1 exposed

<span class="token comment"># 查看service</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get svc svc-nginx -n dev -o wide</span>
NAME         <span class="token function">TYPE</span>        CLUSTER-IP       EXTERNAL-IP   PORT<span class="token punctuation">(</span>S<span class="token punctuation">)</span>   AGE     SELECTOR
svc-nginx1   ClusterIP   10<span class="token punctuation">.</span>109<span class="token punctuation">.</span>179<span class="token punctuation">.</span>231   <none>        80/TCP    3m51s   run=nginx

<span class="token comment"># 这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的</span>
<span class="token comment"># 可以通过这个IP访问当前service对应的POD</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># curl 10.109.179.231:80</span>
<<span class="token operator">!</span>DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!<<span class="token operator">/</span>title>
<<span class="token operator">/</span>head>
<body>
<h1>Welcome to nginx!<<span class="token operator">/</span>h1>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<<span class="token operator">/</span>body>
<<span class="token operator">/</span>html>
</code></pre> 
  <p><strong>操作二:创建集群外部也可访问的Service</strong></p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问</span>
<span class="token comment"># 如果需要创建外部也可以访问的Service,需要修改type为NodePort</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev</span>
service/svc-nginx2 exposed

<span class="token comment"># 此时查看,会发现出现了NodePort类型的Service,而且有一对Port(80:31928/TC)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get svc  svc-nginx-1  -n dev -o wide</span>
NAME          <span class="token function">TYPE</span>        CLUSTER-IP       EXTERNAL-IP   PORT<span class="token punctuation">(</span>S<span class="token punctuation">)</span>        AGE    SELECTOR
svc-nginx2    NodePort    10<span class="token punctuation">.</span>100<span class="token punctuation">.</span>94<span class="token punctuation">.</span>0      <none>        80:31928/TCP   9s     run=nginx

<span class="token comment"># 接下来就可以通过集群外的主机访问 节点IP:31928访问服务了</span>
<span class="token comment"># 例如在的电脑主机上通过浏览器访问下面的地址</span>
http:<span class="token operator">/</span><span class="token operator">/</span>192<span class="token punctuation">.</span>168<span class="token punctuation">.</span>109<span class="token punctuation">.</span>100:31928/
</code></pre> 
  <p><strong>删除Service</strong></p> 
  <pre><code class="prism language-powershell"><span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete svc svc-nginx-1 -n dev                                   service "svc-nginx-1" deleted</span>
</code></pre> 
  <p><strong>配置方式</strong></p> 
  <p>创建一个svc-nginx.yaml,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Service
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> svc<span class="token punctuation">-</span>nginx
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">clusterIP</span><span class="token punctuation">:</span> 10.109.179.231
  <span class="token key atrule">ports</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">80</span>
    <span class="token key atrule">protocol</span><span class="token punctuation">:</span> TCP
    <span class="token key atrule">targetPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
  <span class="token key atrule">selector</span><span class="token punctuation">:</span>
    <span class="token key atrule">run</span><span class="token punctuation">:</span> nginx
  <span class="token key atrule">type</span><span class="token punctuation">:</span> ClusterIP
</code></pre> 
  <p>然后就可以执行对应的创建和删除命令了:</p> 
  <p>​ 创建:kubectl create -f svc-nginx.yaml</p> 
  <p>​ 删除:kubectl delete -f svc-nginx.yaml</p> 
  <blockquote> 
   <p><strong>小结</strong></p> 
   <p>​ 至此,已经掌握了Namespace、Pod、Deployment、Service资源的基本操作,有了这些操作,就可以在kubernetes集群中实现一个服务的简单部署和访问了,但是如果想要更好的使用kubernetes,就需要深入学习这几种资源的细节和原理。</p> 
  </blockquote> 
  <h1>第五章 Pod详解</h1> 
  <p>本章节将详细介绍Pod资源的各种配置(yaml)和原理。</p> 
  <h2>Pod介绍</h2> 
  <h3>Pod结构</h3>  
  <p>每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类:</p> 
  <ul> 
   <li> <p>用户程序所在的容器,数量可多可少</p> </li> 
   <li> <p>Pause容器,这是每个Pod都会有的一个<strong>根容器</strong>,它的作用有两个:</p> 
    <ul> 
     <li> <p>可以以它为依据,评估整个Pod的健康状态</p> </li> 
     <li> <p>可以在根容器上设置Ip地址,其它容器都此Ip(Pod IP),以实现Pod内部的网路通信</p> <pre><code class="prism language-md">这里是Pod内部的通讯,Pod的之间的通讯采用虚拟二层网络技术来实现,我们当前环境用的是Flannel
</code></pre> </li> 
    </ul> </li> 
  </ul> 
  <h3>Pod定义</h3> 
  <p>下面是Pod的资源清单:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1     <span class="token comment">#必选,版本号,例如v1</span>
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod         <span class="token comment">#必选,资源类型,例如 Pod</span>
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>         <span class="token comment">#必选,元数据</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> string     <span class="token comment">#必选,Pod名称</span>
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> string  <span class="token comment">#Pod所属的命名空间,默认为"default"</span>
  <span class="token key atrule">labels</span><span class="token punctuation">:</span>           <span class="token comment">#自定义标签列表</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string                 
<span class="token key atrule">spec</span><span class="token punctuation">:</span>  <span class="token comment">#必选,Pod中容器的详细定义</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>  <span class="token comment">#必选,Pod中容器列表</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string   <span class="token comment">#必选,容器名称</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> string  <span class="token comment">#必选,容器的镜像名称</span>
    <span class="token key atrule">imagePullPolicy</span><span class="token punctuation">:</span> <span class="token punctuation">[</span> Always<span class="token punctuation">|</span>Never<span class="token punctuation">|</span>IfNotPresent <span class="token punctuation">]</span>  <span class="token comment">#获取镜像的策略 </span>
    <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>string<span class="token punctuation">]</span>   <span class="token comment">#容器的启动命令列表,如不指定,使用打包时使用的启动命令</span>
    <span class="token key atrule">args</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>string<span class="token punctuation">]</span>      <span class="token comment">#容器的启动命令参数列表</span>
    <span class="token key atrule">workingDir</span><span class="token punctuation">:</span> string  <span class="token comment">#容器的工作目录</span>
    <span class="token key atrule">volumeMounts</span><span class="token punctuation">:</span>       <span class="token comment">#挂载到容器内部的存储卷配置</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string      <span class="token comment">#引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名</span>
      <span class="token key atrule">mountPath</span><span class="token punctuation">:</span> string <span class="token comment">#存储卷在容器内mount的绝对路径,应少于512字符</span>
      <span class="token key atrule">readOnly</span><span class="token punctuation">:</span> boolean <span class="token comment">#是否为只读模式</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span> <span class="token comment">#需要暴露的端口库号列表</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string        <span class="token comment">#端口的名称</span>
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> int  <span class="token comment">#容器需要监听的端口号</span>
      <span class="token key atrule">hostPort</span><span class="token punctuation">:</span> int       <span class="token comment">#容器所在主机需要监听的端口号,默认与Container相同</span>
      <span class="token key atrule">protocol</span><span class="token punctuation">:</span> string    <span class="token comment">#端口协议,支持TCP和UDP,默认TCP</span>
    <span class="token key atrule">env</span><span class="token punctuation">:</span>   <span class="token comment">#容器运行前需设置的环境变量列表</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string  <span class="token comment">#环境变量名称</span>
      <span class="token key atrule">value</span><span class="token punctuation">:</span> string <span class="token comment">#环境变量的值</span>
    <span class="token key atrule">resources</span><span class="token punctuation">:</span> <span class="token comment">#资源限制和请求的设置</span>
      <span class="token key atrule">limits</span><span class="token punctuation">:</span>  <span class="token comment">#资源限制的设置</span>
        <span class="token key atrule">cpu</span><span class="token punctuation">:</span> string     <span class="token comment">#Cpu的限制,单位为core数,将用于docker run --cpu-shares参数</span>
        <span class="token key atrule">memory</span><span class="token punctuation">:</span> string  <span class="token comment">#内存限制,单位可以为Mib/Gib,将用于docker run --memory参数</span>
      <span class="token key atrule">requests</span><span class="token punctuation">:</span> <span class="token comment">#资源请求的设置</span>
        <span class="token key atrule">cpu</span><span class="token punctuation">:</span> string    <span class="token comment">#Cpu请求,容器启动的初始可用数量</span>
        <span class="token key atrule">memory</span><span class="token punctuation">:</span> string <span class="token comment">#内存请求,容器启动的初始可用数量</span>
    <span class="token key atrule">lifecycle</span><span class="token punctuation">:</span> <span class="token comment">#生命周期钩子</span>
		<span class="token key atrule">postStart</span><span class="token punctuation">:</span> <span class="token comment">#容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启</span>
		<span class="token key atrule">preStop</span><span class="token punctuation">:</span> <span class="token comment">#容器终止前执行此钩子,无论结果如何,容器都会终止</span>
    <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>  <span class="token comment">#对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器</span>
      <span class="token key atrule">exec</span><span class="token punctuation">:</span>         <span class="token comment">#对Pod容器内检查方式设置为exec方式</span>
        <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>string<span class="token punctuation">]</span>  <span class="token comment">#exec方式需要制定的命令或脚本</span>
      <span class="token key atrule">httpGet</span><span class="token punctuation">:</span>       <span class="token comment">#对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port</span>
        <span class="token key atrule">path</span><span class="token punctuation">:</span> string
        <span class="token key atrule">port</span><span class="token punctuation">:</span> number
        <span class="token key atrule">host</span><span class="token punctuation">:</span> string
        <span class="token key atrule">scheme</span><span class="token punctuation">:</span> string
        <span class="token key atrule">HttpHeaders</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string
          <span class="token key atrule">value</span><span class="token punctuation">:</span> string
      <span class="token key atrule">tcpSocket</span><span class="token punctuation">:</span>     <span class="token comment">#对Pod内个容器健康检查方式设置为tcpSocket方式</span>
         <span class="token key atrule">port</span><span class="token punctuation">:</span> number
       <span class="token key atrule">initialDelaySeconds</span><span class="token punctuation">:</span> <span class="token number">0</span>       <span class="token comment">#容器启动完成后首次探测的时间,单位为秒</span>
       <span class="token key atrule">timeoutSeconds</span><span class="token punctuation">:</span> 0          <span class="token comment">#对容器健康检查探测等待响应的超时时间,单位秒,默认1秒</span>
       <span class="token key atrule">periodSeconds</span><span class="token punctuation">:</span> 0           <span class="token comment">#对容器监控检查的定期探测时间设置,单位秒,默认10秒一次</span>
       <span class="token key atrule">successThreshold</span><span class="token punctuation">:</span> <span class="token number">0</span>
       <span class="token key atrule">failureThreshold</span><span class="token punctuation">:</span> <span class="token number">0</span>
       <span class="token key atrule">securityContext</span><span class="token punctuation">:</span>
         <span class="token key atrule">privileged</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>
  <span class="token key atrule">restartPolicy</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>Always <span class="token punctuation">|</span> Never <span class="token punctuation">|</span> OnFailure<span class="token punctuation">]</span>  <span class="token comment">#Pod的重启策略</span>
  <span class="token key atrule">nodeName</span><span class="token punctuation">:</span> <string<span class="token punctuation">></span> <span class="token comment">#设置NodeName表示将该Pod调度到指定到名称的node节点上</span>
  <span class="token key atrule">nodeSelector</span><span class="token punctuation">:</span> obeject <span class="token comment">#设置NodeSelector表示将该Pod调度到包含这个label的node上</span>
  <span class="token key atrule">imagePullSecrets</span><span class="token punctuation">:</span> <span class="token comment">#Pull镜像时使用的secret名称,以key:secretkey格式指定</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string
  <span class="token key atrule">hostNetwork</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>   <span class="token comment">#是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络</span>
  <span class="token key atrule">volumes</span><span class="token punctuation">:</span>   <span class="token comment">#在该pod上定义共享存储卷列表</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> string    <span class="token comment">#共享存储卷名称 (volumes类型有很多种)</span>
    <span class="token key atrule">emptyDir</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>       <span class="token comment">#类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值</span>
    <span class="token key atrule">hostPath</span><span class="token punctuation">:</span> string   <span class="token comment">#类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录</span>
      <span class="token key atrule">path</span><span class="token punctuation">:</span> string                <span class="token comment">#Pod所在宿主机的目录,将被用于同期中mount的目录</span>
    <span class="token key atrule">secret</span><span class="token punctuation">:</span>          <span class="token comment">#类型为secret的存储卷,挂载集群与定义的secret对象到容器内部</span>
      <span class="token key atrule">scretname</span><span class="token punctuation">:</span> string  
      <span class="token key atrule">items</span><span class="token punctuation">:</span>     
      <span class="token punctuation">-</span> <span class="token key atrule">key</span><span class="token punctuation">:</span> string
        <span class="token key atrule">path</span><span class="token punctuation">:</span> string
    <span class="token key atrule">configMap</span><span class="token punctuation">:</span>         <span class="token comment">#类型为configMap的存储卷,挂载预定义的configMap对象到容器内部</span>
      <span class="token key atrule">name</span><span class="token punctuation">:</span> string
      <span class="token key atrule">items</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token key atrule">key</span><span class="token punctuation">:</span> string
        <span class="token key atrule">path</span><span class="token punctuation">:</span> string
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment">#小提示:</span>
<span class="token comment">#	在这里,可通过一个命令来查看每种资源的可配置项</span>
<span class="token comment">#   kubectl explain 资源类型         查看某种资源可以配置的一级属性</span>
<span class="token comment">#	kubectl explain 资源类型.属性     查看属性的子属性</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl explain pod</span>
KIND:     Pod
VERSION:  v1
FIELDS:
   apiVersion   <string>
   kind <string>
   metadata     <Object>
   spec <Object>
   status       <Object>

<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl explain pod.metadata</span>
KIND:     Pod
VERSION:  v1
RESOURCE: metadata <Object>
FIELDS:
   annotations  <map<span class="token namespace">[string]</span>string>
   clusterName  <string>
   creationTimestamp    <string>
   deletionGracePeriodSeconds   <integer>
   deletionTimestamp    <string>
   finalizers   <<span class="token punctuation">[</span><span class="token punctuation">]</span>string>
   generateName <string>
   generation   <integer>
   labels       <map<span class="token namespace">[string]</span>string>
   managedFields        <<span class="token punctuation">[</span><span class="token punctuation">]</span>Object>
   name <string>
   namespace    <string>
   ownerReferences      <<span class="token punctuation">[</span><span class="token punctuation">]</span>Object>
   resourceVersion      <string>
   selfLink     <string>
   uid  <string>
</code></pre> 
  <p>在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:</p> 
  <ul> 
   <li> <p>apiVersion <string> 版本,由kubernetes内部定义,版本号必须可以用 kubectl api-versions 查询到</p> </li> 
   <li> <p>kind <string> 类型,由kubernetes内部定义,版本号必须可以用 kubectl api-resources 查询到</p> </li> 
   <li> <p>metadata <Object> 元数据,主要是资源标识和说明,常用的有name、namespace、labels等</p> </li> 
   <li> <p>spec <Object> 描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述</p> </li> 
   <li> <p>status <Object> 状态信息,里面的内容不需要定义,由kubernetes自动生成</p> </li> 
  </ul> 
  <p>在上面的属性中,spec是接下来研究的重点,继续看下它的常见子属性:</p> 
  <ul> 
   <li>containers <[]Object> 容器列表,用于定义容器的详细信息</li> 
   <li>nodeName <String> 根据nodeName的值将pod调度到指定的Node节点上</li> 
   <li>nodeSelector <map[]> 根据NodeSelector中定义的信息选择将该Pod调度到包含这些label的Node 上</li> 
   <li>hostNetwork <boolean> 是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络</li> 
   <li>volumes <[]Object> 存储卷,用于定义Pod上面挂在的存储信息</li> 
   <li>restartPolicy <string> 重启策略,表示Pod在遇到故障的时候的处理策略</li> 
  </ul> 
  <h2>Pod配置</h2> 
  <p>本小节主要来研究<code>pod.spec.containers</code>属性,这也是pod配置中最为关键的一项配置。</p> 
  <pre><code class="prism language-powershell"><span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl explain pod.spec.containers</span>
KIND:     Pod
VERSION:  v1
RESOURCE: containers <<span class="token punctuation">[</span><span class="token punctuation">]</span>Object>   <span class="token comment"># 数组,代表可以有多个容器</span>
FIELDS:
   name  <string>     <span class="token comment"># 容器名称</span>
   image <string>     <span class="token comment"># 容器需要的镜像地址</span>
   imagePullPolicy  <string> <span class="token comment"># 镜像拉取策略 </span>
   command  <<span class="token punctuation">[</span><span class="token punctuation">]</span>string> <span class="token comment"># 容器的启动命令列表,如不指定,使用打包时使用的启动命令</span>
   args     <<span class="token punctuation">[</span><span class="token punctuation">]</span>string> <span class="token comment"># 容器的启动命令需要的参数列表</span>
   env      <<span class="token punctuation">[</span><span class="token punctuation">]</span>Object> <span class="token comment"># 容器环境变量的配置</span>
   ports    <<span class="token punctuation">[</span><span class="token punctuation">]</span>Object>     <span class="token comment"># 容器需要暴露的端口号列表</span>
   resources <Object>      <span class="token comment"># 资源限制和资源请求的设置</span>
</code></pre> 
  <h3>基本配置</h3> 
  <p>创建pod-base.yaml文件,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>base
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
  <span class="token key atrule">labels</span><span class="token punctuation">:</span>
    <span class="token key atrule">user</span><span class="token punctuation">:</span> heima
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> busybox
    <span class="token key atrule">image</span><span class="token punctuation">:</span> busybox<span class="token punctuation">:</span><span class="token number">1.30</span>
</code></pre> 
  <p>上面定义了一个比较简单Pod的配置,里面有两个容器:</p> 
  <ul> 
   <li>nginx:用1.17.1版本的nginx镜像创建,(nginx是一个轻量级web容器)</li> 
   <li>busybox:用1.30版本的busybox镜像创建,(busybox是一个小巧的linux命令集合)</li> 
  </ul> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl apply -f pod-base.yaml</span>
pod/pod-base created

<span class="token comment"># 查看Pod状况</span>
<span class="token comment"># READY 1/2 : 表示当前Pod中有2个容器,其中1个准备就绪,1个未就绪</span>
<span class="token comment"># RESTARTS  : 重启次数,因为有1个容器故障了,Pod一直在重启试图恢复它</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl get pod -n dev</span>
NAME       READY   STATUS    RESTARTS   AGE
pod-base   1/2     Running   4          95s

<span class="token comment"># 可以通过describe查看内部的详情</span>
<span class="token comment"># 此时已经运行起来了一个基本的Pod,虽然它暂时有问题</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl describe pod pod-base -n dev</span>
</code></pre> 
  <h3>镜像拉取</h3> 
  <p>创建pod-imagepullpolicy.yaml文件,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>imagepullpolicy
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">imagePullPolicy</span><span class="token punctuation">:</span> Always <span class="token comment"># 用于设置镜像拉取策略</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> busybox
    <span class="token key atrule">image</span><span class="token punctuation">:</span> busybox<span class="token punctuation">:</span><span class="token number">1.30</span>
</code></pre> 
  <p>imagePullPolicy,用于设置镜像拉取策略,kubernetes支持配置三种拉取策略:</p> 
  <ul> 
   <li>Always:总是从远程仓库拉取镜像(一直远程下载)</li> 
   <li>IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地 本地没远程下载)</li> 
   <li>Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错 (一直使用本地)</li> 
  </ul> 
  <blockquote> 
   <p>默认值说明:</p> 
   <p>​ 如果镜像tag为具体版本号, 默认策略是:IfNotPresent</p> 
   <p>​ 如果镜像tag为:latest(最终版本) ,默认策略是always</p> 
  </blockquote> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl create -f pod-imagepullpolicy.yaml</span>
pod/pod-imagepullpolicy created

<span class="token comment"># 查看Pod详情</span>
<span class="token comment"># 此时明显可以看到nginx镜像有一步Pulling image "nginx:1.17.1"的过程</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl describe pod pod-imagepullpolicy -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
Events:
  <span class="token function">Type</span>     Reason     Age               <span class="token keyword">From</span>               Message
  <span class="token operator">--</span><span class="token operator">--</span>     <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>     <span class="token operator">--</span><span class="token operator">--</span>              <span class="token operator">--</span><span class="token operator">--</span>               <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>
  Normal   Scheduled  <unknown>         default-scheduler  Successfully assigned dev/pod-imagePullPolicy to node1
  Normal   Pulling    32s               kubelet<span class="token punctuation">,</span> node1     Pulling image <span class="token string">"nginx:1.17.1"</span>
  Normal   Pulled     26s               kubelet<span class="token punctuation">,</span> node1     Successfully pulled image <span class="token string">"nginx:1.17.1"</span>
  Normal   Created    26s               kubelet<span class="token punctuation">,</span> node1     Created container nginx
  Normal   Started    25s               kubelet<span class="token punctuation">,</span> node1     Started container nginx
  Normal   Pulled     7s <span class="token punctuation">(</span>x3 over 25s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Container image <span class="token string">"busybox:1.30"</span> already present on machine
  Normal   Created    7s <span class="token punctuation">(</span>x3 over 25s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Created container busybox
  Normal   Started    7s <span class="token punctuation">(</span>x3 over 25s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Started container busybox
</code></pre> 
  <h3>启动命令</h3> 
  <p>​ 在前面的案例中,一直有一个问题没有解决,就是的busybox容器一直没有成功运行,那么到底是什么原因导致这个容器的故障呢?</p> 
  <p>​ 原来busybox并不是一个程序,而是类似于一个工具类的集合,kubernetes集群启动管理后,它会自动关闭。解决方法就是让其一直在运行,这就用到了command配置。</p> 
  <p>创建pod-command.yaml文件,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>command
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> busybox
    <span class="token key atrule">image</span><span class="token punctuation">:</span> busybox<span class="token punctuation">:</span><span class="token number">1.30</span>
    <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"/bin/sh"</span><span class="token punctuation">,</span><span class="token string">"-c"</span><span class="token punctuation">,</span><span class="token string">"touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"</span><span class="token punctuation">]</span>
</code></pre> 
  <p>command,用于在pod中的容器初始化完毕之后运行一个命令。</p> 
  <blockquote> 
   <p>稍微解释下上面命令的意思:</p> 
   <p>​ “/bin/sh”,“-c”, 使用sh执行命令</p> 
   <p>​ touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件</p> 
   <p>​ while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中写入当前时间</p> 
  </blockquote> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl create  -f pod-command.yaml</span>
pod/pod-command created

<span class="token comment"># 查看Pod状态</span>
<span class="token comment"># 此时发现两个pod都正常运行了</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl get pods pod-command -n dev</span>
NAME          READY   STATUS   RESTARTS   AGE
pod-command   2/2     Runing   0          2s

<span class="token comment"># 进入pod中的busybox容器,查看文件内容</span>
<span class="token comment"># 补充一个命令: kubectl exec  pod名称 -n 命名空间 -it -c 容器名称 /bin/sh  在容器内部执行命令</span>
<span class="token comment"># 使用这个命令就可以进入某个容器的内部,然后进行相关操作了</span>
<span class="token comment"># 比如,可以查看txt文件的内容</span>
<span class="token namespace">[root@master pod]</span><span class="token comment"># kubectl exec pod-command -n dev -it -c busybox /bin/sh</span>
<span class="token operator">/</span> <span class="token comment"># tail -f /tmp/hello.txt</span>
13:35:35
13:35:38
13:35:41
</code></pre> 
  <pre><code class="prism language-md">特别说明:
    通过上面发现command已经可以完成启动命令和传递参数的功能,为什么这里还要提供一个args选项,用于传递参数呢?这其实跟docker有点关系,kubernetes中的command、args两项其实是实现覆盖Dockerfile中ENTRYPOINT的功能。
 1 如果command和args均没有写,那么用Dockerfile的配置。
 2 如果command写了,但args没有写,那么Dockerfile默认的配置会被忽略,执行输入的command
 3 如果command没写,但args写了,那么Dockerfile中配置的ENTRYPOINT的命令会被执行,使用当前args的参数
 4 如果command和args都写了,那么Dockerfile的配置被忽略,执行command并追加上args参数
</code></pre> 
  <h3>环境变量</h3> 
  <p>创建pod-env.yaml文件,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>env
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> busybox
    <span class="token key atrule">image</span><span class="token punctuation">:</span> busybox<span class="token punctuation">:</span><span class="token number">1.30</span>
    <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"/bin/sh"</span><span class="token punctuation">,</span><span class="token string">"-c"</span><span class="token punctuation">,</span><span class="token string">"while true;do /bin/echo $(date +%T);sleep 60; done;"</span><span class="token punctuation">]</span>
    <span class="token key atrule">env</span><span class="token punctuation">:</span> <span class="token comment"># 设置环境变量列表</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">"username"</span>
      <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"admin"</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> <span class="token string">"password"</span>
      <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"123456"</span>
</code></pre> 
  <p>env,环境变量,用于在pod中的容器设置环境变量。</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-env.yaml</span>
pod/pod-env created

<span class="token comment"># 进入容器,输出环境变量</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl exec pod-env -n dev -c busybox -it /bin/sh</span>
<span class="token operator">/</span> <span class="token comment"># echo $username</span>
admin
<span class="token operator">/</span> <span class="token comment"># echo $password</span>
123456
</code></pre> 
  <p>这种方式不是很推荐,推荐将这些配置单独存储在配置文件中,这种方式将在后面介绍。</p> 
  <h3>端口设置</h3> 
  <p>本小节来介绍容器的端口设置,也就是containers的ports选项。</p> 
  <p>首先看下ports支持的子选项:</p> 
  <pre><code class="prism language-powershell"><span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl explain pod.spec.containers.ports</span>
KIND:     Pod
VERSION:  v1
RESOURCE: ports <<span class="token punctuation">[</span><span class="token punctuation">]</span>Object>
FIELDS:
   name         <string>  <span class="token comment"># 端口名称,如果指定,必须保证name在pod中是唯一的		</span>
   containerPort<integer> <span class="token comment"># 容器要监听的端口(0<x<65536)</span>
   hostPort     <integer> <span class="token comment"># 容器要在主机上公开的端口,如果设置,主机上只能运行容器的一个副本(一般省略) </span>
   hostIP       <string>  <span class="token comment"># 要将外部端口绑定到的主机IP(一般省略)</span>
   protocol     <string>  <span class="token comment"># 端口协议。必须是UDP、TCP或SCTP。默认为“TCP”。</span>
</code></pre> 
  <p>接下来,编写一个测试案例,创建pod-ports.yaml</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>ports
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span> <span class="token comment"># 设置容器暴露的端口列表</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
      <span class="token key atrule">protocol</span><span class="token punctuation">:</span> TCP
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-ports.yaml</span>
pod/pod-ports created

<span class="token comment"># 查看pod</span>
<span class="token comment"># 在下面可以明显看到配置信息</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod pod-ports -n dev -o yaml</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
spec:
  containers:
  <span class="token operator">-</span> image: nginx:1<span class="token punctuation">.</span>17<span class="token punctuation">.</span>1
    imagePullPolicy: IfNotPresent
    name: nginx
    ports:
    <span class="token operator">-</span> containerPort: 80
      name: nginx-port
      protocol: TCP
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
</code></pre> 
  <p>访问容器中的程序需要使用的是<code>podIp:containerPort</code></p> 
  <h3>资源配额</h3> 
  <p>​ 容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量资源,导致其它容器无法运行。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现,他有两个子选项:</p> 
  <ul> 
   <li> <p>limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启</p> </li> 
   <li> <p>requests :用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动</p> </li> 
  </ul> 
  <p>可以通过上面两个选项设置资源的上下限。</p> 
  <p>接下来,编写一个测试案例,创建pod-resources.yaml</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>resources
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">resources</span><span class="token punctuation">:</span> <span class="token comment"># 资源配额</span>
      <span class="token key atrule">limits</span><span class="token punctuation">:</span>  <span class="token comment"># 限制资源(上限)</span>
        <span class="token key atrule">cpu</span><span class="token punctuation">:</span> <span class="token string">"2"</span> <span class="token comment"># CPU限制,单位是core数</span>
        <span class="token key atrule">memory</span><span class="token punctuation">:</span> <span class="token string">"10Gi"</span> <span class="token comment"># 内存限制</span>
      <span class="token key atrule">requests</span><span class="token punctuation">:</span> <span class="token comment"># 请求资源(下限)</span>
        <span class="token key atrule">cpu</span><span class="token punctuation">:</span> <span class="token string">"1"</span>  <span class="token comment"># CPU限制,单位是core数</span>
        <span class="token key atrule">memory</span><span class="token punctuation">:</span> <span class="token string">"10Mi"</span>  <span class="token comment"># 内存限制</span>
</code></pre> 
  <p>在这对cpu和memory的单位做一个说明:</p> 
  <ul> 
   <li> <p>cpu:core数,可以为整数或小数</p> </li> 
   <li> <p>memory: 内存大小,可以使用Gi、Mi、G、M等形式</p> </li> 
  </ul> 
  <pre><code class="prism language-powershell"><span class="token comment"># 运行Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create  -f pod-resources.yaml</span>
pod/pod-resources created

<span class="token comment"># 查看发现pod运行正常</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod pod-resources -n dev</span>
NAME            READY   STATUS    RESTARTS   AGE  
pod-resources   1/1     Running   0          39s   

<span class="token comment"># 接下来,停止Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete  -f pod-resources.yaml</span>
pod <span class="token string">"pod-resources"</span> deleted

<span class="token comment"># 编辑pod,修改resources.requests.memory的值为10Gi</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># vim pod-resources.yaml</span>

<span class="token comment"># 再次启动pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create  -f pod-resources.yaml</span>
pod/pod-resources created

<span class="token comment"># 查看Pod状态,发现Pod启动失败</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod pod-resources -n dev -o wide</span>
NAME            READY   STATUS    RESTARTS   AGE          
pod-resources   0/2     Pending   0          20s    

<span class="token comment"># 查看pod详情会发现,如下提示</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe pod pod-resources -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
Warning  FailedScheduling  <unknown>  default-scheduler  0/2 nodes are available: 2 Insufficient memory<span class="token punctuation">.</span><span class="token punctuation">(</span>内存不足<span class="token punctuation">)</span>
</code></pre> 
  <h2>Pod生命周期</h2> 
  <p>我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:</p> 
  <ul> 
   <li> <p>pod创建过程</p> </li> 
   <li> <p>运行初始化容器(init container)过程</p> </li> 
   <li> <p>运行主容器(main container)</p> 
    <ul> 
     <li> <p>容器启动后钩子(post start)、容器终止前钩子(pre stop)</p> </li> 
     <li> <p>容器的存活性探测(liveness probe)、就绪性探测(readiness probe)</p> </li> 
    </ul> </li> 
   <li> <p>pod终止过程</p> </li> 
  </ul>  
  <p>在整个生命周期中,Pod会出现5种<strong>状态</strong>(<strong>相位</strong>),分别如下:</p> 
  <ul> 
   <li>挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中</li> 
   <li>运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成</li> 
   <li>成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启</li> 
   <li>失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态</li> 
   <li>未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致</li> 
  </ul> 
  <h3>创建和终止</h3> 
  <p><strong>pod的创建过程</strong></p> 
  <ol> 
   <li> <p>用户通过kubectl或其他api客户端提交需要创建的pod信息给apiServer</p> </li> 
   <li> <p>apiServer开始生成pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端</p> </li> 
   <li> <p>apiServer开始反映etcd中的pod对象的变化,其它组件使用watch机制来跟踪检查apiServer上的变动</p> </li> 
   <li> <p>scheduler发现有新的pod对象要创建,开始为Pod分配主机并将结果信息更新至apiServer</p> </li> 
   <li> <p>node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiServer</p> </li> 
   <li> <p>apiServer将接收到的pod状态信息存入etcd中</p>  </li> 
  </ol> 
  <p><strong>pod的终止过程</strong></p> 
  <ol> 
   <li>用户向apiServer发送删除pod对象的命令</li> 
   <li>apiServcer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead</li> 
   <li>将pod标记为terminating状态</li> 
   <li>kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程</li> 
   <li>端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除</li> 
   <li>如果当前pod对象定义了preStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行</li> 
   <li>pod对象中的容器进程收到停止信号</li> 
   <li>宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号</li> 
   <li>kubelet请求apiServer将此pod资源的宽限期设置为0从而完成删除操作,此时pod对于用户已不可见</li> 
  </ol> 
  <h3>初始化容器</h3> 
  <p>初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:</p> 
  <ol> 
   <li>初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成</li> 
   <li>初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行</li> 
  </ol> 
  <p>初始化容器有很多的应用场景,下面列出的是最常见的几个:</p> 
  <ul> 
   <li>提供主容器镜像中不具备的工具程序或自定义代码</li> 
   <li>初始化容器要先于应用容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足</li> 
  </ul> 
  <p>接下来做一个案例,模拟下面这个需求:</p> 
  <p>​ 假设要以主容器来运行nginx,但是要求在运行nginx之前先要能够连接上mysql和redis所在服务器</p> 
  <p>​ 为了简化测试,事先规定好mysql<code>(192.168.109.201)</code>和redis<code>(192.168.109.202)</code>服务器的地址</p> 
  <p>创建pod-initcontainer.yaml,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>initcontainer
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> main<span class="token punctuation">-</span>container
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span> 
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
  <span class="token key atrule">initContainers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> test<span class="token punctuation">-</span>mysql
    <span class="token key atrule">image</span><span class="token punctuation">:</span> busybox<span class="token punctuation">:</span><span class="token number">1.30</span>
    <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'sh'</span><span class="token punctuation">,</span> <span class="token string">'-c'</span><span class="token punctuation">,</span> <span class="token string">'until ping 192.168.109.201 -c 1 ; do echo waiting for mysql...; sleep 2; done;'</span><span class="token punctuation">]</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> test<span class="token punctuation">-</span>redis
    <span class="token key atrule">image</span><span class="token punctuation">:</span> busybox<span class="token punctuation">:</span><span class="token number">1.30</span>
    <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'sh'</span><span class="token punctuation">,</span> <span class="token string">'-c'</span><span class="token punctuation">,</span> <span class="token string">'until ping 192.168.109.202 -c 1 ; do echo waiting for reids...; sleep 2; done;'</span><span class="token punctuation">]</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-initcontainer.yaml</span>
pod/pod-initcontainer created

<span class="token comment"># 查看pod状态</span>
<span class="token comment"># 发现pod卡在启动第一个初始化容器过程中,后面的容器不会运行</span>
root@master ~<span class="token punctuation">]</span><span class="token comment"># kubectl describe pod  pod-initcontainer -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
Events:
  <span class="token function">Type</span>    Reason     Age   <span class="token keyword">From</span>               Message
  <span class="token operator">--</span><span class="token operator">--</span>    <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>     <span class="token operator">--</span><span class="token operator">--</span>  <span class="token operator">--</span><span class="token operator">--</span>               <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>
  Normal  Scheduled  49s   default-scheduler  Successfully assigned dev/pod-initcontainer to node1
  Normal  Pulled     48s   kubelet<span class="token punctuation">,</span> node1     Container image <span class="token string">"busybox:1.30"</span> already present on machine
  Normal  Created    48s   kubelet<span class="token punctuation">,</span> node1     Created container <span class="token function">test-mysql</span>
  Normal  Started    48s   kubelet<span class="token punctuation">,</span> node1     Started container <span class="token function">test-mysql</span>

<span class="token comment"># 动态查看pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-initcontainer -n dev -w</span>
NAME                             READY   STATUS     RESTARTS   AGE
pod-initcontainer                0/1     Init:0/2   0          15s
pod-initcontainer                0/1     Init:1/2   0          52s
pod-initcontainer                0/1     Init:1/2   0          53s
pod-initcontainer                0/1     PodInitializing   0          89s
pod-initcontainer                1/1     Running           0          90s

<span class="token comment"># 接下来新开一个shell,为当前服务器新增两个ip,观察pod的变化</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># ifconfig ens33:1 192.168.109.201 netmask 255.255.255.0 up</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># ifconfig ens33:2 192.168.109.202 netmask 255.255.255.0 up</span>
</code></pre> 
  <h3>钩子函数</h3> 
  <p>钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。</p> 
  <p>kubernetes在主容器的启动之后和停止之前提供了两个钩子函数:</p> 
  <ul> 
   <li>post start:容器创建之后执行,如果失败了会重启容器</li> 
   <li>pre stop :容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作</li> 
  </ul> 
  <p>钩子处理器支持使用下面三种方式定义动作:</p> 
  <ul> 
   <li> <p>Exec命令:在容器内执行一次命令</p> <pre><code class="prism language-yaml">……
  <span class="token key atrule">lifecycle</span><span class="token punctuation">:</span>
    <span class="token key atrule">postStart</span><span class="token punctuation">:</span> 
      <span class="token key atrule">exec</span><span class="token punctuation">:</span>
        <span class="token key atrule">command</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> cat
        <span class="token punctuation">-</span> /tmp/healthy
……
</code></pre> </li> 
   <li> <p>TCPSocket:在当前容器尝试访问指定的socket</p> <pre><code class="prism language-yaml">……      
  <span class="token key atrule">lifecycle</span><span class="token punctuation">:</span>
    <span class="token key atrule">postStart</span><span class="token punctuation">:</span>
      <span class="token key atrule">tcpSocket</span><span class="token punctuation">:</span>
        <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8080</span>
……
</code></pre> </li> 
   <li> <p>HTTPGet:在当前容器中向某url发起http请求</p> <pre><code class="prism language-yaml">……
  <span class="token key atrule">lifecycle</span><span class="token punctuation">:</span>
    <span class="token key atrule">postStart</span><span class="token punctuation">:</span>
      <span class="token key atrule">httpGet</span><span class="token punctuation">:</span>
        <span class="token key atrule">path</span><span class="token punctuation">:</span> / <span class="token comment">#URI地址</span>
        <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">80</span> <span class="token comment">#端口号</span>
        <span class="token key atrule">host</span><span class="token punctuation">:</span> 192.168.109.100 <span class="token comment">#主机地址</span>
        <span class="token key atrule">scheme</span><span class="token punctuation">:</span> HTTP <span class="token comment">#支持的协议,http或者https</span>
……
</code></pre> </li> 
  </ul> 
  <p>接下来,以exec方式为例,演示下钩子函数的使用,创建pod-hook-exec.yaml文件,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>hook<span class="token punctuation">-</span>exec
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> main<span class="token punctuation">-</span>container
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
    <span class="token key atrule">lifecycle</span><span class="token punctuation">:</span>
      <span class="token key atrule">postStart</span><span class="token punctuation">:</span> 
        <span class="token key atrule">exec</span><span class="token punctuation">:</span> <span class="token comment"># 在容器启动的时候执行一个命令,修改掉nginx的默认首页内容</span>
          <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"/bin/sh"</span><span class="token punctuation">,</span> <span class="token string">"-c"</span><span class="token punctuation">,</span> <span class="token string">"echo postStart... > /usr/share/nginx/html/index.html"</span><span class="token punctuation">]</span>
      <span class="token key atrule">preStop</span><span class="token punctuation">:</span>
        <span class="token key atrule">exec</span><span class="token punctuation">:</span> <span class="token comment"># 在容器停止之前停止nginx服务</span>
          <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"/usr/sbin/nginx"</span><span class="token punctuation">,</span><span class="token string">"-s"</span><span class="token punctuation">,</span><span class="token string">"quit"</span><span class="token punctuation">]</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-hook-exec.yaml</span>
pod/pod-hook-exec created

<span class="token comment"># 查看pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods  pod-hook-exec -n dev -o wide</span>
NAME           READY   STATUS     RESTARTS   AGE    IP            NODE    
pod-hook-exec  1/1     Running    0          29s    10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>2<span class="token punctuation">.</span>48   node2   

<span class="token comment"># 访问pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># curl 10.244.2.48</span>
postStart<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
</code></pre> 
  <h3>容器探测</h3> 
  <p>​ 容器探测用于检测容器中的应用实例是否正常工作,是保障业务可用性的一种传统机制。如果经过探测,实例的状态不符合预期,那么kubernetes就会把该问题实例" 摘除 ",不承担业务流量。kubernetes提供了两种探针来实现容器探测,分别是:</p> 
  <ul> 
   <li> <p>liveness probes:存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器</p> </li> 
   <li> <p>readiness probes:就绪性探针,用于检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量</p> </li> 
  </ul> 
  <blockquote> 
   <p>livenessProbe 决定是否重启容器,readinessProbe 决定是否将请求转发给容器。</p> 
  </blockquote> 
  <p>上面两种探针目前均支持三种探测方式:</p> 
  <ul> 
   <li> <p>Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常</p> <pre><code class="prism language-yaml">……
  <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
    <span class="token key atrule">exec</span><span class="token punctuation">:</span>
      <span class="token key atrule">command</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> cat
      <span class="token punctuation">-</span> /tmp/healthy
……
</code></pre> </li> 
   <li> <p>TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常</p> <pre><code class="prism language-yaml">……      
  <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
    <span class="token key atrule">tcpSocket</span><span class="token punctuation">:</span>
      <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8080</span>
……
</code></pre> </li> 
   <li> <p>HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常</p> <pre><code class="prism language-yaml">……
  <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
    <span class="token key atrule">httpGet</span><span class="token punctuation">:</span>
      <span class="token key atrule">path</span><span class="token punctuation">:</span> / <span class="token comment">#URI地址</span>
      <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">80</span> <span class="token comment">#端口号</span>
      <span class="token key atrule">host</span><span class="token punctuation">:</span> 127.0.0.1 <span class="token comment">#主机地址</span>
      <span class="token key atrule">scheme</span><span class="token punctuation">:</span> HTTP <span class="token comment">#支持的协议,http或者https</span>
……
</code></pre> </li> 
  </ul> 
  <p>下面以liveness probes为例,做几个演示:</p> 
  <p><strong>方式一:Exec</strong></p> 
  <p>创建pod-liveness-exec.yaml</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>liveness<span class="token punctuation">-</span>exec
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span> 
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
    <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
      <span class="token key atrule">exec</span><span class="token punctuation">:</span>
        <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"/bin/cat"</span><span class="token punctuation">,</span><span class="token string">"/tmp/hello.txt"</span><span class="token punctuation">]</span> <span class="token comment"># 执行一个查看文件的命令</span>
</code></pre> 
  <p>创建pod,观察效果</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-liveness-exec.yaml</span>
pod/pod-liveness-exec created

<span class="token comment"># 查看Pod详情</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe pods pod-liveness-exec -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
  Normal   Created    20s <span class="token punctuation">(</span>x2 over 50s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Created container nginx
  Normal   Started    20s <span class="token punctuation">(</span>x2 over 50s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Started container nginx
  Normal   Killing    20s                kubelet<span class="token punctuation">,</span> node1     Container nginx failed liveness probe<span class="token punctuation">,</span> will be restarted
  Warning  Unhealthy  0s <span class="token punctuation">(</span>x5 over 40s<span class="token punctuation">)</span>   kubelet<span class="token punctuation">,</span> node1     Liveness probe failed: <span class="token function">cat</span>: can<span class="token string">'t open '</span><span class="token operator">/</span>tmp/hello11<span class="token punctuation">.</span>txt': No such file or directory
  
<span class="token comment"># 观察上面的信息就会发现nginx容器启动之后就进行了健康检查</span>
<span class="token comment"># 检查失败之后,容器被kill掉,然后尝试进行重启(这是重启策略的作用,后面讲解)</span>
<span class="token comment"># 稍等一会之后,再观察pod信息,就可以看到RESTARTS不再是0,而是一直增长</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-liveness-exec -n dev</span>
NAME                READY   STATUS             RESTARTS   AGE
pod-liveness-exec   0/1     CrashLoopBackOff   2          3m19s

<span class="token comment"># 当然接下来,可以修改成一个存在的文件,比如/tmp/hello.txt,再试,结果就正常了......</span>
</code></pre> 
  <p><strong>方式二:TCPSocket</strong></p> 
  <p>创建pod-liveness-tcpsocket.yaml</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>liveness<span class="token punctuation">-</span>tcpsocket
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span> 
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
    <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
      <span class="token key atrule">tcpSocket</span><span class="token punctuation">:</span>
        <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8080</span> <span class="token comment"># 尝试访问8080端口</span>
</code></pre> 
  <p>创建pod,观察效果</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-liveness-tcpsocket.yaml</span>
pod/pod-liveness-tcpsocket created

<span class="token comment"># 查看Pod详情</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe pods pod-liveness-tcpsocket -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
  Normal   Scheduled  31s                            default-scheduler  Successfully assigned dev/pod-liveness-tcpsocket to node2
  Normal   Pulled     <invalid>                      kubelet<span class="token punctuation">,</span> node2     Container image <span class="token string">"nginx:1.17.1"</span> already present on machine
  Normal   Created    <invalid>                      kubelet<span class="token punctuation">,</span> node2     Created container nginx
  Normal   Started    <invalid>                      kubelet<span class="token punctuation">,</span> node2     Started container nginx
  Warning  Unhealthy  <invalid> <span class="token punctuation">(</span>x2 over <invalid><span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node2     Liveness probe failed: dial tcp 10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>2<span class="token punctuation">.</span>44:8080: connect: connection refused
  
<span class="token comment"># 观察上面的信息,发现尝试访问8080端口,但是失败了</span>
<span class="token comment"># 稍等一会之后,再观察pod信息,就可以看到RESTARTS不再是0,而是一直增长</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-liveness-tcpsocket  -n dev</span>
NAME                     READY   STATUS             RESTARTS   AGE
pod-liveness-tcpsocket   0/1     CrashLoopBackOff   2          3m19s

<span class="token comment"># 当然接下来,可以修改成一个可以访问的端口,比如80,再试,结果就正常了......</span>
</code></pre> 
  <p><strong>方式三:HTTPGet</strong></p> 
  <p>创建pod-liveness-httpget.yaml</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>liveness<span class="token punctuation">-</span>httpget
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
    <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
      <span class="token key atrule">httpGet</span><span class="token punctuation">:</span>  <span class="token comment"># 其实就是访问http://127.0.0.1:80/hello  </span>
        <span class="token key atrule">scheme</span><span class="token punctuation">:</span> HTTP <span class="token comment">#支持的协议,http或者https</span>
        <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">80</span> <span class="token comment">#端口号</span>
        <span class="token key atrule">path</span><span class="token punctuation">:</span> /hello <span class="token comment">#URI地址</span>
</code></pre> 
  <p>创建pod,观察效果</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-liveness-httpget.yaml</span>
pod/pod-liveness-httpget created

<span class="token comment"># 查看Pod详情</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe pod pod-liveness-httpget -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
  Normal   Pulled     6s <span class="token punctuation">(</span>x3 over 64s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Container image <span class="token string">"nginx:1.17.1"</span> already present on machine
  Normal   Created    6s <span class="token punctuation">(</span>x3 over 64s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Created container nginx
  Normal   Started    6s <span class="token punctuation">(</span>x3 over 63s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Started container nginx
  Warning  Unhealthy  6s <span class="token punctuation">(</span>x6 over 56s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    6s <span class="token punctuation">(</span>x2 over 36s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Container nginx failed liveness probe<span class="token punctuation">,</span> will be restarted
  
<span class="token comment"># 观察上面信息,尝试访问路径,但是未找到,出现404错误</span>
<span class="token comment"># 稍等一会之后,再观察pod信息,就可以看到RESTARTS不再是0,而是一直增长</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod pod-liveness-httpget -n dev</span>
NAME                   READY   STATUS    RESTARTS   AGE
pod-liveness-httpget   1/1     Running   5          3m17s

<span class="token comment"># 当然接下来,可以修改成一个可以访问的路径path,比如/,再试,结果就正常了......</span>
</code></pre> 
  <p>​ 至此,已经使用liveness Probe演示了三种探测方式,但是查看livenessProbe的子属性,会发现除了这三种方式,还有一些其他的配置,在这里一并解释下:</p> 
  <pre><code class="prism language-powershell"><span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl explain pod.spec.containers.livenessProbe</span>
FIELDS:
   exec <Object>  
   tcpSocket    <Object>
   httpGet      <Object>
   initialDelaySeconds  <integer>  <span class="token comment"># 容器启动后等待多少秒执行第一次探测</span>
   timeoutSeconds       <integer>  <span class="token comment"># 探测超时时间。默认1秒,最小1秒</span>
   periodSeconds        <integer>  <span class="token comment"># 执行探测的频率。默认是10秒,最小1秒</span>
   failureThreshold     <integer>  <span class="token comment"># 连续探测失败多少次才被认定为失败。默认是3。最小值是1</span>
   successThreshold     <integer>  <span class="token comment"># 连续探测成功多少次才被认定为成功。默认是1</span>
</code></pre> 
  <p>下面稍微配置两个,演示下效果即可:</p> 
  <pre><code class="prism language-yaml"><span class="token punctuation">[</span>root@master ~<span class="token punctuation">]</span><span class="token comment"># more pod-liveness-httpget.yaml</span>
<span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>liveness<span class="token punctuation">-</span>httpget
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
    <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
      <span class="token key atrule">httpGet</span><span class="token punctuation">:</span>
        <span class="token key atrule">scheme</span><span class="token punctuation">:</span> HTTP
        <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">80</span> 
        <span class="token key atrule">path</span><span class="token punctuation">:</span> /
      <span class="token key atrule">initialDelaySeconds</span><span class="token punctuation">:</span> <span class="token number">30</span> <span class="token comment"># 容器启动后30s开始探测</span>
      <span class="token key atrule">timeoutSeconds</span><span class="token punctuation">:</span> <span class="token number">5</span> <span class="token comment"># 探测超时时间为5s</span>
</code></pre> 
  <h3>重启策略</h3> 
  <p>​ 在上一节中,一旦容器探测出现了问题,kubernetes就会对容器所在的Pod进行重启,其实这是由pod的重启策略决定的,pod的重启策略有 3 种,分别如下:</p> 
  <ul> 
   <li>Always :容器失效时,自动重启该容器,这也是默认值。</li> 
   <li>OnFailure : 容器终止运行且退出码不为0时重启</li> 
   <li>Never : 不论状态为何,都不重启该容器</li> 
  </ul> 
  <p>​ 重启策略适用于pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长以此为10s、20s、40s、80s、160s和300s,300s是最大延迟时长。</p> 
  <p>创建pod-restartpolicy.yaml:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>restartpolicy
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>port
      <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
    <span class="token key atrule">livenessProbe</span><span class="token punctuation">:</span>
      <span class="token key atrule">httpGet</span><span class="token punctuation">:</span>
        <span class="token key atrule">scheme</span><span class="token punctuation">:</span> HTTP
        <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">80</span>
        <span class="token key atrule">path</span><span class="token punctuation">:</span> /hello
  <span class="token key atrule">restartPolicy</span><span class="token punctuation">:</span> Never <span class="token comment"># 设置重启策略为Never</span>
</code></pre> 
  <p>运行Pod测试</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-restartpolicy.yaml</span>
pod/pod-restartpolicy created

<span class="token comment"># 查看Pod详情,发现nginx容器失败</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl  describe pods pod-restartpolicy  -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
  Warning  Unhealthy  15s <span class="token punctuation">(</span>x3 over 35s<span class="token punctuation">)</span>  kubelet<span class="token punctuation">,</span> node1     Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    15s                kubelet<span class="token punctuation">,</span> node1     Container nginx failed liveness probe
  
<span class="token comment"># 多等一会,再观察pod的重启次数,发现一直是0,并未重启   </span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl  get pods pod-restartpolicy -n dev</span>
NAME                   READY   STATUS    RESTARTS   AGE
pod-restartpolicy      0/1     Running   0          5min42s
</code></pre> 
  <h2>Pod调度</h2> 
  <p>​ 在默认情况下,一个Pod在哪个Node节点上运行,是由Scheduler组件采用相应的算法计算出来的,这个过程是不受人工控制的。但是在实际使用中,这并不满足的需求,因为很多情况下,我们想控制某些Pod到达某些节点上,那么应该怎么做呢?这就要求了解kubernetes对Pod的调度规则,kubernetes提供了四大类调度方式:</p> 
  <ul> 
   <li>自动调度:运行在哪个节点上完全由Scheduler经过一系列的算法计算得出</li> 
   <li>定向调度:NodeName、NodeSelector</li> 
   <li>亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity</li> 
   <li>污点(容忍)调度:Taints、Toleration</li> 
  </ul> 
  <h3>定向调度</h3> 
  <p>​ 定向调度,指的是利用在pod上声明nodeName或者nodeSelector,以此将Pod调度到期望的node节点上。注意,这里的调度是强制的,这就意味着即使要调度的目标Node不存在,也会向上面进行调度,只不过pod运行失败而已。</p> 
  <p><strong>NodeName</strong></p> 
  <p>​ NodeName用于强制约束将Pod调度到指定的Name的Node节点上。这种方式,其实是直接跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点。</p> 
  <p>接下来,实验一下:创建一个pod-nodename.yaml文件</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>nodename
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">nodeName</span><span class="token punctuation">:</span> node1 <span class="token comment"># 指定调度到node1节点上</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment">#创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-nodename.yaml</span>
pod/pod-nodename created

<span class="token comment">#查看Pod调度到NODE属性,确实是调度到了node1节点上</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-nodename -n dev -o wide</span>
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE      <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
pod-nodename   1/1     Running   0          56s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>87   node1     <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>   

<span class="token comment"># 接下来,删除pod,修改nodeName的值为node3(并没有node3节点)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete -f pod-nodename.yaml</span>
pod <span class="token string">"pod-nodename"</span> deleted
<span class="token namespace">[root@master ~]</span><span class="token comment"># vim pod-nodename.yaml</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-nodename.yaml</span>
pod/pod-nodename created

<span class="token comment">#再次查看,发现已经向Node3节点调度,但是由于不存在node3节点,所以pod无法正常运行</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-nodename -n dev -o wide</span>
NAME           READY   STATUS    RESTARTS   AGE   IP       NODE    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
pod-nodename   0/1     Pending   0          6s    <none>   node3   <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>           
</code></pre> 
  <p><strong>NodeSelector</strong></p> 
  <p>​ NodeSelector用于将pod调度到添加了指定标签的node节点上。它是通过kubernetes的label-selector机制实现的,也就是说,在pod创建之前,会由scheduler使用MatchNodeSelector调度策略进行label匹配,找出目标node,然后将pod调度到目标节点,该匹配规则是强制约束。</p> 
  <p>接下来,实验一下:</p> 
  <p>1 首先分别为node节点添加标签</p> 
  <pre><code class="prism language-powershell"><span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl label nodes node1 nodeenv=pro</span>
node/node2 labeled
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl label nodes node2 nodeenv=test</span>
node/node2 labeled
</code></pre> 
  <p>2 创建一个pod-nodeselector.yaml文件,并使用它创建Pod</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>nodeselector
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">nodeSelector</span><span class="token punctuation">:</span> 
    <span class="token key atrule">nodeenv</span><span class="token punctuation">:</span> pro <span class="token comment"># 指定调度到具有nodeenv=pro标签的节点上</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment">#创建Pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-nodeselector.yaml</span>
pod/pod-nodeselector created

<span class="token comment">#查看Pod调度到NODE属性,确实是调度到了node1节点上</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-nodeselector -n dev -o wide</span>
NAME               READY   STATUS    RESTARTS   AGE     IP          NODE    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
pod-nodeselector   1/1     Running   0          47s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>87   node1   <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

<span class="token comment"># 接下来,删除pod,修改nodeSelector的值为nodeenv: xxxx(不存在打有此标签的节点)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete -f pod-nodeselector.yaml</span>
pod <span class="token string">"pod-nodeselector"</span> deleted
<span class="token namespace">[root@master ~]</span><span class="token comment"># vim pod-nodeselector.yaml</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-nodeselector.yaml</span>
pod/pod-nodeselector created

<span class="token comment">#再次查看,发现pod无法正常运行,Node的值为none</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev -o wide</span>
NAME               READY   STATUS    RESTARTS   AGE     IP       NODE    
pod-nodeselector   0/1     Pending   0          2m20s   <none>   <none>

<span class="token comment"># 查看详情,发现node selector匹配失败的提示</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe pods pod-nodeselector -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
Events:
  <span class="token function">Type</span>     Reason            Age        <span class="token keyword">From</span>               Message
  <span class="token operator">--</span><span class="token operator">--</span>     <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>            <span class="token operator">--</span><span class="token operator">--</span>       <span class="token operator">--</span><span class="token operator">--</span>               <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node<span class="token punctuation">(</span>s<span class="token punctuation">)</span> didn<span class="token string">'t match node selector.
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn'</span>t match node selector<span class="token punctuation">.</span>
</code></pre> 
  <h3>亲和性调度</h3> 
  <p>​ 上一节,介绍了两种定向调度的方式,使用起来非常方便,但是也有一定的问题,那就是如果没有满足条件的Node,那么Pod将不会被运行,即使在集群中还有可用Node列表也不行,这就限制了它的使用场景。</p> 
  <p>​ 基于上面的问题,kubernetes还提供了一种亲和性调度(Affinity)。它在NodeSelector的基础之上的进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使调度更加灵活。</p> 
  <p>Affinity主要分为三类:</p> 
  <ul> 
   <li> <p>nodeAffinity(node亲和性): 以node为目标,解决pod可以调度到哪些node的问题</p> </li> 
   <li> <p>podAffinity(pod亲和性) : 以pod为目标,解决pod可以和哪些已存在的pod部署在同一个拓扑域中的问题</p> </li> 
   <li> <p>podAntiAffinity(pod反亲和性) : 以pod为目标,解决pod不能和哪些已存在pod部署在同一个拓扑域中的问题</p> </li> 
  </ul> 
  <blockquote> 
   <p>关于亲和性(反亲和性)使用场景的说明:</p> 
   <p><strong>亲和性</strong>:如果两个应用频繁交互,那就有必要利用亲和性让两个应用的尽可能的靠近,这样可以减少因网络通信而带来的性能损耗。</p> 
   <p><strong>反亲和性</strong>:当应用的采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,这样可以提高服务的高可用性。</p> 
  </blockquote> 
  <p><strong>NodeAffinity</strong></p> 
  <p>首先来看一下<code>NodeAffinity</code>的可配置项:</p> 
  <pre><code class="prism language-markdown">pod.spec.affinity.nodeAffinity
  requiredDuringSchedulingIgnoredDuringExecution  Node节点必须满足指定的所有规则才可以,相当于硬限制
    nodeSelectorTerms  节点选择列表
      matchFields   按节点字段列出的节点选择器要求列表
      matchExpressions   按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt
  preferredDuringSchedulingIgnoredDuringExecution 优先调度到满足指定的规则的Node,相当于软限制 (倾向)
    preference   一个节点选择器项,与相应的权重相关联
      matchFields   按节点字段列出的节点选择器要求列表
      matchExpressions   按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt
	weight 倾向权重,在范围1-100。
</code></pre> 
  <pre><code class="prism language-markdown">关系符的使用说明:

- matchExpressions:
  - key: nodeenv              # 匹配存在标签的key为nodeenv的节点
    operator: Exists
  - key: nodeenv              # 匹配标签的key为nodeenv,且value是"xxx"或"yyy"的节点
    operator: In
    values: ["xxx","yyy"]
  - key: nodeenv              # 匹配标签的key为nodeenv,且value大于"xxx"的节点
    operator: Gt
    values: "xxx"
</code></pre> 
  <p>接下来首先演示一下<code>requiredDuringSchedulingIgnoredDuringExecution</code> ,</p> 
  <p>创建pod-nodeaffinity-required.yaml</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>nodeaffinity<span class="token punctuation">-</span>required
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">affinity</span><span class="token punctuation">:</span>  <span class="token comment">#亲和性设置</span>
    <span class="token key atrule">nodeAffinity</span><span class="token punctuation">:</span> <span class="token comment">#设置node亲和性</span>
      <span class="token key atrule">requiredDuringSchedulingIgnoredDuringExecution</span><span class="token punctuation">:</span> <span class="token comment"># 硬限制</span>
        <span class="token key atrule">nodeSelectorTerms</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">matchExpressions</span><span class="token punctuation">:</span> <span class="token comment"># 匹配env的值在["xxx","yyy"]中的标签</span>
          <span class="token punctuation">-</span> <span class="token key atrule">key</span><span class="token punctuation">:</span> nodeenv
            <span class="token key atrule">operator</span><span class="token punctuation">:</span> In
            <span class="token key atrule">values</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"xxx"</span><span class="token punctuation">,</span><span class="token string">"yyy"</span><span class="token punctuation">]</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-nodeaffinity-required.yaml</span>
pod/pod-nodeaffinity-required created

<span class="token comment"># 查看pod状态 (运行失败)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-nodeaffinity-required -n dev -o wide</span>
NAME                        READY   STATUS    RESTARTS   AGE   IP       NODE    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> 
pod-nodeaffinity-required   0/1     Pending   0          16s   <none>   <none>  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

<span class="token comment"># 查看Pod的详情</span>
<span class="token comment"># 发现调度失败,提示node选择失败</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe pod pod-nodeaffinity-required -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node<span class="token punctuation">(</span>s<span class="token punctuation">)</span> didn<span class="token string">'t match node selector.
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn'</span>t match node selector<span class="token punctuation">.</span>

<span class="token comment">#接下来,停止pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete -f pod-nodeaffinity-required.yaml</span>
pod <span class="token string">"pod-nodeaffinity-required"</span> deleted

<span class="token comment"># 修改文件,将values: ["xxx","yyy"]------> ["pro","yyy"]</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># vim pod-nodeaffinity-required.yaml</span>

<span class="token comment"># 再次启动</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-nodeaffinity-required.yaml</span>
pod/pod-nodeaffinity-required created

<span class="token comment"># 此时查看,发现调度成功,已经将pod调度到了node1上</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-nodeaffinity-required -n dev -o wide</span>
NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> 
pod-nodeaffinity-required   1/1     Running   0          11s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>89   node1 <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
</code></pre> 
  <p>接下来再演示一下<code>requiredDuringSchedulingIgnoredDuringExecution</code> ,</p> 
  <p>创建pod-nodeaffinity-preferred.yaml</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>nodeaffinity<span class="token punctuation">-</span>preferred
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">affinity</span><span class="token punctuation">:</span>  <span class="token comment">#亲和性设置</span>
    <span class="token key atrule">nodeAffinity</span><span class="token punctuation">:</span> <span class="token comment">#设置node亲和性</span>
      <span class="token key atrule">preferredDuringSchedulingIgnoredDuringExecution</span><span class="token punctuation">:</span> <span class="token comment"># 软限制</span>
      <span class="token punctuation">-</span> <span class="token key atrule">weight</span><span class="token punctuation">:</span> <span class="token number">1</span>
        <span class="token key atrule">preference</span><span class="token punctuation">:</span>
          <span class="token key atrule">matchExpressions</span><span class="token punctuation">:</span> <span class="token comment"># 匹配env的值在["xxx","yyy"]中的标签(当前环境没有)</span>
          <span class="token punctuation">-</span> <span class="token key atrule">key</span><span class="token punctuation">:</span> nodeenv
            <span class="token key atrule">operator</span><span class="token punctuation">:</span> In
            <span class="token key atrule">values</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"xxx"</span><span class="token punctuation">,</span><span class="token string">"yyy"</span><span class="token punctuation">]</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-nodeaffinity-preferred.yaml</span>
pod/pod-nodeaffinity-preferred created

<span class="token comment"># 查看pod状态 (运行成功)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pod pod-nodeaffinity-preferred -n dev</span>
NAME                         READY   STATUS    RESTARTS   AGE
pod-nodeaffinity-preferred   1/1     Running   0          40s
</code></pre> 
  <pre><code class="prism language-markdown">NodeAffinity规则设置的注意事项:
    1 如果同时定义了nodeSelector和nodeAffinity,那么必须两个条件都得到满足,Pod才能运行在指定的Node上
    2 如果nodeAffinity指定了多个nodeSelectorTerms,那么只需要其中一个能够匹配成功即可
    3 如果一个nodeSelectorTerms中有多个matchExpressions ,则一个节点必须满足所有的才能匹配成功
    4 如果一个pod所在的Node在Pod运行期间其标签发生了改变,不再符合该Pod的节点亲和性需求,则系统将忽略此变化
</code></pre> 
  <p><strong>PodAffinity</strong></p> 
  <p>PodAffinity主要实现以运行的Pod为参照,实现让新创建的Pod跟参照pod在一个区域的功能。</p> 
  <p>首先来看一下<code>PodAffinity</code>的可配置项:</p> 
  <pre><code class="prism language-markdown">pod.spec.affinity.podAffinity
  requiredDuringSchedulingIgnoredDuringExecution  硬限制
    namespaces       指定参照pod的namespace
    topologyKey      指定调度作用域
    labelSelector    标签选择器
      matchExpressions  按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持In, NotIn, Exists, DoesNotExist.
      matchLabels    指多个matchExpressions映射的内容
  preferredDuringSchedulingIgnoredDuringExecution 软限制
    podAffinityTerm  选项
      namespaces      
      topologyKey
      labelSelector
        matchExpressions  
          key    键
          values 值
          operator
        matchLabels 
    weight 倾向权重,在范围1-100
</code></pre> 
  <pre><code class="prism language-markdown">topologyKey用于指定调度时作用域,例如:
    如果指定为kubernetes.io/hostname,那就是以Node节点为区分范围
	如果指定为beta.kubernetes.io/os,则以Node节点的操作系统类型来区分
</code></pre> 
  <p>接下来,演示下<code>requiredDuringSchedulingIgnoredDuringExecution</code>,</p> 
  <p>1)首先创建一个参照Pod,pod-podaffinity-target.yaml:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>podaffinity<span class="token punctuation">-</span>target
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
  <span class="token key atrule">labels</span><span class="token punctuation">:</span>
    <span class="token key atrule">podenv</span><span class="token punctuation">:</span> pro <span class="token comment">#设置标签</span>
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">nodeName</span><span class="token punctuation">:</span> node1 <span class="token comment"># 将目标pod名确指定到node1上</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment"># 启动目标pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-podaffinity-target.yaml</span>
pod/pod-podaffinity-target created

<span class="token comment"># 查看pod状况</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods  pod-podaffinity-target -n dev</span>
NAME                     READY   STATUS    RESTARTS   AGE
pod-podaffinity-target   1/1     Running   0          4s
</code></pre> 
  <p>2)创建pod-podaffinity-required.yaml,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>podaffinity<span class="token punctuation">-</span>required
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">affinity</span><span class="token punctuation">:</span>  <span class="token comment">#亲和性设置</span>
    <span class="token key atrule">podAffinity</span><span class="token punctuation">:</span> <span class="token comment">#设置pod亲和性</span>
      <span class="token key atrule">requiredDuringSchedulingIgnoredDuringExecution</span><span class="token punctuation">:</span> <span class="token comment"># 硬限制</span>
      <span class="token punctuation">-</span> <span class="token key atrule">labelSelector</span><span class="token punctuation">:</span>
          <span class="token key atrule">matchExpressions</span><span class="token punctuation">:</span> <span class="token comment"># 匹配env的值在["xxx","yyy"]中的标签</span>
          <span class="token punctuation">-</span> <span class="token key atrule">key</span><span class="token punctuation">:</span> podenv
            <span class="token key atrule">operator</span><span class="token punctuation">:</span> In
            <span class="token key atrule">values</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"xxx"</span><span class="token punctuation">,</span><span class="token string">"yyy"</span><span class="token punctuation">]</span>
        <span class="token key atrule">topologyKey</span><span class="token punctuation">:</span> kubernetes.io/hostname
</code></pre> 
  <p>上面配置表达的意思是:新Pod必须要与拥有标签nodeenv=xxx或者nodeenv=yyy的pod在同一Node上,显然现在没有这样pod,接下来,运行测试一下。</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 启动pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-podaffinity-required.yaml</span>
pod/pod-podaffinity-required created

<span class="token comment"># 查看pod状态,发现未运行</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-podaffinity-required -n dev</span>
NAME                       READY   STATUS    RESTARTS   AGE
pod-podaffinity-required   0/1     Pending   0          9s

<span class="token comment"># 查看详细信息</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl describe pods pod-podaffinity-required  -n dev</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
Events:
  <span class="token function">Type</span>     Reason            Age        <span class="token keyword">From</span>               Message
  <span class="token operator">--</span><span class="token operator">--</span>     <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span>            <span class="token operator">--</span><span class="token operator">--</span>       <span class="token operator">--</span><span class="token operator">--</span>               <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 2 node<span class="token punctuation">(</span>s<span class="token punctuation">)</span> didn<span class="token string">'t match pod affinity rules, 1 node(s) had taints that the pod didn'</span>t tolerate<span class="token punctuation">.</span>

<span class="token comment"># 接下来修改  values: ["xxx","yyy"]----->values:["pro","yyy"]</span>
<span class="token comment"># 意思是:新Pod必须要与拥有标签nodeenv=xxx或者nodeenv=yyy的pod在同一Node上</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># vim pod-podaffinity-required.yaml</span>

<span class="token comment"># 然后重新创建pod,查看效果</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl delete -f  pod-podaffinity-required.yaml</span>
pod <span class="token string">"pod-podaffinity-required"</span> deleted
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-podaffinity-required.yaml</span>
pod/pod-podaffinity-required created

<span class="token comment"># 发现此时Pod运行正常</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-podaffinity-required -n dev</span>
NAME                       READY   STATUS    RESTARTS   AGE   LABELS
pod-podaffinity-required   1/1     Running   0          6s    <none>
</code></pre> 
  <p>关于<code>PodAffinity</code>的 <code>preferredDuringSchedulingIgnoredDuringExecution</code>,这里不再演示。</p> 
  <p><strong>PodAntiAffinity</strong></p> 
  <p>PodAntiAffinity主要实现以运行的Pod为参照,让新创建的Pod跟参照pod不在一个区域中的功能。</p> 
  <p>它的配置方式和选项跟PodAffinty是一样的,这里不再做详细解释,直接做一个测试案例。</p> 
  <p>1)继续使用上个案例中目标pod</p> 
  <pre><code class="prism language-powershell"><span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev -o wide --show-labels</span>
NAME                     READY   STATUS    RESTARTS   AGE     IP            NODE    LABELS
pod-podaffinity-required 1/1     Running   0          3m29s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>38   node1   <none>     
pod-podaffinity-target   1/1     Running   0          9m25s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>37   node1   podenv=pro
</code></pre> 
  <p>2)创建pod-podantiaffinity-required.yaml,内容如下:</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>podantiaffinity<span class="token punctuation">-</span>required
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">affinity</span><span class="token punctuation">:</span>  <span class="token comment">#亲和性设置</span>
    <span class="token key atrule">podAntiAffinity</span><span class="token punctuation">:</span> <span class="token comment">#设置pod亲和性</span>
      <span class="token key atrule">requiredDuringSchedulingIgnoredDuringExecution</span><span class="token punctuation">:</span> <span class="token comment"># 硬限制</span>
      <span class="token punctuation">-</span> <span class="token key atrule">labelSelector</span><span class="token punctuation">:</span>
          <span class="token key atrule">matchExpressions</span><span class="token punctuation">:</span> <span class="token comment"># 匹配podenv的值在["pro"]中的标签</span>
          <span class="token punctuation">-</span> <span class="token key atrule">key</span><span class="token punctuation">:</span> podenv
            <span class="token key atrule">operator</span><span class="token punctuation">:</span> In
            <span class="token key atrule">values</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"pro"</span><span class="token punctuation">]</span>
        <span class="token key atrule">topologyKey</span><span class="token punctuation">:</span> kubernetes.io/hostname
</code></pre> 
  <p>上面配置表达的意思是:新Pod必须要与拥有标签nodeenv=pro的pod不在同一Node上,运行测试一下。</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 创建pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl create -f pod-podantiaffinity-required.yaml</span>
pod/pod-podantiaffinity-required created

<span class="token comment"># 查看pod</span>
<span class="token comment"># 发现调度到了node2上</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods pod-podantiaffinity-required -n dev -o wide</span>
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE   <span class="token punctuation">.</span><span class="token punctuation">.</span> 
pod-podantiaffinity-required   1/1     Running   0          30s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>96   node2  <span class="token punctuation">.</span><span class="token punctuation">.</span>
</code></pre> 
  <h3>污点和容忍</h3> 
  <p><strong>污点(Taints)</strong></p> 
  <p>​ 前面的调度方式都是站在Pod的角度上,通过在Pod上添加属性,来确定Pod是否要调度到指定的Node上,其实我们也可以站在Node的角度上,通过在Node上添加<strong>污点</strong>属性,来决定是否允许Pod调度过来。</p> 
  <p>​ Node被设置上污点之后就和Pod之间存在了一种相斥的关系,进而拒绝Pod调度进来,甚至可以将已经存在的Pod驱逐出去。</p> 
  <p>污点的格式为:<code>key=value:effect</code>, key和value是污点的标签,effect描述污点的作用,支持如下三个选项:</p> 
  <ul> 
   <li>PreferNoSchedule:kubernetes将尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可调度</li> 
   <li>NoSchedule:kubernetes将不会把Pod调度到具有该污点的Node上,但不会影响当前Node上已存在的Pod</li> 
   <li>NoExecute:kubernetes将不会把Pod调度到具有该污点的Node上,同时也会将Node上已存在的Pod驱离</li> 
  </ul>  
  <p>使用kubectl设置和去除污点的命令示例如下:</p> 
  <pre><code class="prism language-powershell"><span class="token comment"># 设置污点</span>
kubectl taint nodes node1 key=value:effect

<span class="token comment"># 去除污点</span>
kubectl taint nodes node1 key:effect-

<span class="token comment"># 去除所有污点</span>
kubectl taint nodes node1 key-
</code></pre> 
  <p>接下来,演示下污点的效果:</p> 
  <ol> 
   <li>准备节点node1(为了演示效果更加明显,暂时停止node2节点)</li> 
   <li>为node1节点设置一个污点: <code>tag=heima:PreferNoSchedule</code>;然后创建pod1( pod1 可以 )</li> 
   <li>修改为node1节点设置一个污点: <code>tag=heima:NoSchedule</code>;然后创建pod2( pod1 正常 pod2 失败 )</li> 
   <li>修改为node1节点设置一个污点: <code>tag=heima:NoExecute</code>;然后创建pod3 ( 3个pod都失败 )</li> 
  </ol> 
  <pre><code class="prism language-powershell"><span class="token comment"># 为node1设置污点(PreferNoSchedule)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl taint nodes node1 tag=heima:PreferNoSchedule</span>

<span class="token comment"># 创建pod1</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl run taint1 --image=nginx:1.17.1 -n dev</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev -o wide</span>
NAME                      READY   STATUS    RESTARTS   AGE     IP           NODE   
taint1-7665f7fd85-574h4   1/1     Running   0          2m24s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>59   node1    

<span class="token comment"># 为node1设置污点(取消PreferNoSchedule,设置NoSchedule)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl taint nodes node1 tag:PreferNoSchedule-</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl taint nodes node1 tag=heima:NoSchedule</span>

<span class="token comment"># 创建pod2</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl run taint2 --image=nginx:1.17.1 -n dev</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods taint2 -n dev -o wide</span>
NAME                      READY   STATUS    RESTARTS   AGE     IP            NODE
taint1-7665f7fd85-574h4   1/1     Running   0          2m24s   10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>59   node1 
taint2-544694789-6zmlf    0/1     Pending   0          21s     <none>        <none>   

<span class="token comment"># 为node1设置污点(取消NoSchedule,设置NoExecute)</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl taint nodes node1 tag:NoSchedule-</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl taint nodes node1 tag=heima:NoExecute</span>

<span class="token comment"># 创建pod3</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl run taint3 --image=nginx:1.17.1 -n dev</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev -o wide</span>
NAME                      READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED 
taint1-7665f7fd85-htkmp   0/1     Pending   0          35s   <none>   <none>   <none>    
taint2-544694789-bn7wb    0/1     Pending   0          35s   <none>   <none>   <none>     
taint3-6d78dbd749-tktkq   0/1     Pending   0          6s    <none>   <none>   <none>     
</code></pre> 
  <pre><code class="prism language-markdown">小提示:
    使用kubeadm搭建的集群,默认就会给master节点添加一个污点标记,所以pod就不会调度到master节点上.
</code></pre> 
  <p><strong>容忍(Toleration)</strong></p> 
  <p>​ 上面介绍了污点的作用,我们可以在node上添加污点用于拒绝pod调度上来,但是如果就是想将一个pod调度到一个有污点的node上去,这时候应该怎么做呢?这就要使用到<strong>容忍</strong>。</p> 
  <p>[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8q6rbBPQ-1691505645136)(assets/image-20200514095913741.png)]</p> 
  <blockquote> 
   <p>污点就是拒绝,容忍就是忽略,Node通过污点拒绝pod调度上去,Pod通过容忍忽略拒绝</p> 
  </blockquote> 
  <p>下面先通过一个案例看下效果:</p> 
  <ol> 
   <li>上一小节,已经在node1节点上打上了<code>NoExecute</code>的污点,此时pod是调度不上去的</li> 
   <li>本小节,可以通过给pod添加容忍,然后将其调度上去</li> 
  </ol> 
  <p>创建pod-toleration.yaml,内容如下</p> 
  <pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> pod<span class="token punctuation">-</span>toleration
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> dev
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span>1.17.1
  <span class="token key atrule">tolerations</span><span class="token punctuation">:</span>      <span class="token comment"># 添加容忍</span>
  <span class="token punctuation">-</span> <span class="token key atrule">key</span><span class="token punctuation">:</span> <span class="token string">"tag"</span>        <span class="token comment"># 要容忍的污点的key</span>
    <span class="token key atrule">operator</span><span class="token punctuation">:</span> <span class="token string">"Equal"</span> <span class="token comment"># 操作符</span>
    <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"heima"</span>    <span class="token comment"># 容忍的污点的value</span>
    <span class="token key atrule">effect</span><span class="token punctuation">:</span> <span class="token string">"NoExecute"</span>   <span class="token comment"># 添加容忍的规则,这里必须和标记的污点规则相同</span>
</code></pre> 
  <pre><code class="prism language-powershell"><span class="token comment"># 添加容忍之前的pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev -o wide</span>
NAME             READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED 
pod-toleration   0/1     Pending   0          3s    <none>   <none>   <none>           

<span class="token comment"># 添加容忍之后的pod</span>
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl get pods -n dev -o wide</span>
NAME             READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED
pod-toleration   1/1     Running   0          3s    10<span class="token punctuation">.</span>244<span class="token punctuation">.</span>1<span class="token punctuation">.</span>62   node1   <none>        
</code></pre> 
  <p>下面看一下容忍的详细配置:</p> 
  <pre><code class="prism language-powershell"><span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl explain pod.spec.tolerations</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
FIELDS:
   key       <span class="token comment"># 对应着要容忍的污点的键,空意味着匹配所有的键</span>
   value     <span class="token comment"># 对应着要容忍的污点的值</span>
   operator  <span class="token comment"># key-value的运算符,支持Equal和Exists(默认)</span>
   effect    <span class="token comment"># 对应污点的effect,空意味着匹配所有影响</span>
   tolerationSeconds   <span class="token comment"># 容忍时间, 当effect为NoExecute时生效,表示pod在Node上的停留时间</span>
</code></pre> 
 </div> 
</div>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1689054789134004224"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(kubernetes,算法)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1835513803861749760.htm"
                           title="机器学习与深度学习间关系与区别" target="_blank">机器学习与深度学习间关系与区别</a>
                        <span class="text-muted">ℒℴѵℯ心·动ꦿ໊ོ꫞</span>
<a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>一、机器学习概述定义机器学习(MachineLearning,ML)是一种通过数据驱动的方法,利用统计学和计算算法来训练模型,使计算机能够从数据中学习并自动进行预测或决策。机器学习通过分析大量数据样本,识别其中的模式和规律,从而对新的数据进行判断。其核心在于通过训练过程,让模型不断优化和提升其预测准确性。主要类型1.监督学习(SupervisedLearning)监督学习是指在训练数据集中包含输入</div>
                    </li>
                    <li><a href="/article/1835504470440636416.htm"
                           title="Goolge earth studio 进阶4——路径修改与平滑" target="_blank">Goolge earth studio 进阶4——路径修改与平滑</a>
                        <span class="text-muted">陟彼高冈yu</span>
<a class="tag" taget="_blank" href="/search/Google/1.htm">Google</a><a class="tag" taget="_blank" href="/search/earth/1.htm">earth</a><a class="tag" taget="_blank" href="/search/studio/1.htm">studio</a><a class="tag" taget="_blank" href="/search/%E8%BF%9B%E9%98%B6%E6%95%99%E7%A8%8B/1.htm">进阶教程</a><a class="tag" taget="_blank" href="/search/%E6%97%85%E6%B8%B8/1.htm">旅游</a>
                        <div>如果我们希望在大约中途时获得更多的城市鸟瞰视角。可以将相机拖动到这里并创建一个新的关键帧。camera_target_clip_7EarthStudio会自动平滑我们的路径,所以当我们通过这个关键帧时,不是一个生硬的角度,而是一个平滑的曲线。camera_target_clip_8路径上有贝塞尔控制手柄,允许我们调整路径的形状。右键单击,我们可以选择“平滑路径”,这是默认的自动平滑算法,或者我们可</div>
                    </li>
                    <li><a href="/article/1835502451877310464.htm"
                           title="基于社交网络算法优化的二维最大熵图像分割" target="_blank">基于社交网络算法优化的二维最大熵图像分割</a>
                        <span class="text-muted">智能算法研学社(Jack旭)</span>
<a class="tag" taget="_blank" href="/search/%E6%99%BA%E8%83%BD%E4%BC%98%E5%8C%96%E7%AE%97%E6%B3%95%E5%BA%94%E7%94%A8/1.htm">智能优化算法应用</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E5%83%8F%E5%88%86%E5%89%B2/1.htm">图像分割</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/php/1.htm">php</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>智能优化算法应用:基于社交网络优化的二维最大熵图像阈值分割-附代码文章目录智能优化算法应用:基于社交网络优化的二维最大熵图像阈值分割-附代码1.前言2.二维最大熵阈值分割原理3.基于社交网络优化的多阈值分割4.算法结果:5.参考文献:6.Matlab代码摘要:本文介绍基于最大熵的图像分割,并且应用社交网络算法进行阈值寻优。1.前言阅读此文章前,请阅读《图像分割:直方图区域划分及信息统计介绍》htt</div>
                    </li>
                    <li><a href="/article/1835494538001608704.htm"
                           title="121. 买卖股票的最佳时机" target="_blank">121. 买卖股票的最佳时机</a>
                        <span class="text-muted">薄荷糖的味道_fb40</span>

                        <div>给定一个数组,它的第i个元素是一支给定股票第i天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。示例1:输入:[7,1,5,3,6,4]输出:5解释:在第2天(股票价格=1)的时候买入,在第5天(股票价格=6)的时候卖出,最大利润=6-1=5。注意利润不能是7-1=6,因为卖出价格需要大于买入价格。示例2:输入:</div>
                    </li>
                    <li><a href="/article/1835493753557708800.htm"
                           title="每日算法&面试题,大厂特训二十八天——第二十天(树)" target="_blank">每日算法&面试题,大厂特训二十八天——第二十天(树)</a>
                        <span class="text-muted">肥学</span>
<a class="tag" taget="_blank" href="/search/%E2%9A%A1%E7%AE%97%E6%B3%95%E9%A2%98%E2%9A%A1%E9%9D%A2%E8%AF%95%E9%A2%98%E6%AF%8F%E6%97%A5%E7%B2%BE%E8%BF%9B/1.htm">⚡算法题⚡面试题每日精进</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a>
                        <div>目录标题导读算法特训二十八天面试题点击直接资料领取导读肥友们为了更好的去帮助新同学适应算法和面试题,最近我们开始进行专项突击一步一步来。上一期我们完成了动态规划二十一天现在我们进行下一项对各类算法进行二十八天的一个小总结。还在等什么快来一起肥学进行二十八天挑战吧!!特别介绍小白练手专栏,适合刚入手的新人欢迎订阅编程小白进阶python有趣练手项目里面包括了像《机器人尬聊》《恶搞程序》这样的有趣文章</div>
                    </li>
                    <li><a href="/article/1835492109709307904.htm"
                           title="回溯算法-重新安排行程" target="_blank">回溯算法-重新安排行程</a>
                        <span class="text-muted">chirou_</span>
<a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E8%AE%BA/1.htm">图论</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E6%90%9C%E7%B4%A2/1.htm">图搜索</a>
                        <div>leetcode332.重新安排行程这题我还没自己ac过,只能现在凭着刚学完的热乎劲把我对题解的理解记下来。本题我认为对数据结构的考察比较多,用什么数据结构去存数据,去读取数据,都是很重要的。classSolution{private:unordered_map>targets;boolbacktracking(intticketNum,vector&result){//1.确定参数和返回值//2</div>
                    </li>
                    <li><a href="/article/1835488702881689600.htm"
                           title="Faiss:高效相似性搜索与聚类的利器" target="_blank">Faiss:高效相似性搜索与聚类的利器</a>
                        <span class="text-muted">网络·魚</span>
<a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/faiss/1.htm">faiss</a>
                        <div>Faiss是一个针对大规模向量集合的相似性搜索库,由FacebookAIResearch开发。它提供了一系列高效的算法和数据结构,用于加速向量之间的相似性搜索,特别是在大规模数据集上。本文将介绍Faiss的原理、核心功能以及如何在实际项目中使用它。Faiss原理:近似最近邻搜索:Faiss的核心功能之一是近似最近邻搜索,它能够高效地在大规模数据集中找到与给定查询向量最相似的向量。这种搜索是近似的,</div>
                    </li>
                    <li><a href="/article/1835477614848995328.htm"
                           title="insert into select 主键自增_mybatis拦截器实现主键自动生成" target="_blank">insert into select 主键自增_mybatis拦截器实现主键自动生成</a>
                        <span class="text-muted">weixin_39521651</span>
<a class="tag" taget="_blank" href="/search/insert/1.htm">insert</a><a class="tag" taget="_blank" href="/search/into/1.htm">into</a><a class="tag" taget="_blank" href="/search/select/1.htm">select</a><a class="tag" taget="_blank" href="/search/%E4%B8%BB%E9%94%AE%E8%87%AA%E5%A2%9E/1.htm">主键自增</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/delete%E8%BF%94%E5%9B%9E%E5%80%BC/1.htm">delete返回值</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/insert%E8%BF%94%E5%9B%9E%E4%B8%BB%E9%94%AE/1.htm">insert返回主键</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/insert%E8%BF%94%E5%9B%9E%E5%AF%B9%E8%B1%A1/1.htm">insert返回对象</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/plus/1.htm">plus</a><a class="tag" taget="_blank" href="/search/insert%E8%BF%94%E5%9B%9E%E4%B8%BB%E9%94%AE/1.htm">insert返回主键</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/plus/1.htm">plus</a><a class="tag" taget="_blank" href="/search/%E6%8F%92%E5%85%A5%E7%94%9F%E6%88%90id/1.htm">插入生成id</a>
                        <div>前言前阵子和朋友聊天,他说他们项目有个需求,要实现主键自动生成,不想每次新增的时候,都手动设置主键。于是我就问他,那你们数据库表设置主键自动递增不就得了。他的回答是他们项目目前的id都是采用雪花算法来生成,因此为了项目稳定性,不会切换id的生成方式。朋友问我有没有什么实现思路,他们公司的orm框架是mybatis,我就建议他说,不然让你老大把mybatis切换成mybatis-plus。mybat</div>
                    </li>
                    <li><a href="/article/1835477110530076672.htm"
                           title="k均值聚类算法考试例题_k均值算法(k均值聚类算法计算题)" target="_blank">k均值聚类算法考试例题_k均值算法(k均值聚类算法计算题)</a>
                        <span class="text-muted">寻找你83497</span>
<a class="tag" taget="_blank" href="/search/k%E5%9D%87%E5%80%BC%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95%E8%80%83%E8%AF%95%E4%BE%8B%E9%A2%98/1.htm">k均值聚类算法考试例题</a>
                        <div>?算法:第一步:选K个初始聚类中心,z1(1),z2(1),…,zK(1),其中括号内的序号为寻找聚类中心的迭代运算的次序号。聚类中心的向量值可任意设定,例如可选开始的K个.k均值聚类:---------一种硬聚类算法,隶属度只有两个取值0或1,提出的基本根据是“类内误差平方和最小化”准则;模糊的c均值聚类算法:--------一种模糊聚类算法,是.K均值聚类算法是先随机选取K个对象作为初始的聚类</div>
                    </li>
                    <li><a href="/article/1835469798838988800.htm"
                           title="Python实现简单的机器学习算法" target="_blank">Python实现简单的机器学习算法</a>
                        <span class="text-muted">master_chenchengg</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%8A%9E%E5%85%AC%E6%95%88%E7%8E%87/1.htm">办公效率</a><a class="tag" taget="_blank" href="/search/python%E5%BC%80%E5%8F%91/1.htm">python开发</a><a class="tag" taget="_blank" href="/search/IT/1.htm">IT</a>
                        <div>Python实现简单的机器学习算法开篇:初探机器学习的奇妙之旅搭建环境:一切从安装开始必备工具箱第一步:安装Anaconda和JupyterNotebook小贴士:如何配置Python环境变量算法初体验:从零开始的Python机器学习线性回归:让数据说话数据准备:从哪里找数据编码实战:Python实现线性回归模型评估:如何判断模型好坏逻辑回归:从分类开始理论入门:什么是逻辑回归代码实现:使用skl</div>
                    </li>
                    <li><a href="/article/1835466269948735488.htm"
                           title="推荐算法_隐语义-梯度下降" target="_blank">推荐算法_隐语义-梯度下降</a>
                        <span class="text-muted">_feivirus_</span>
<a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%92%8C%E6%95%B0%E5%AD%A6/1.htm">机器学习和数学</a><a class="tag" taget="_blank" href="/search/%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95/1.htm">推荐算法</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E9%9A%90%E8%AF%AD%E4%B9%89/1.htm">隐语义</a>
                        <div>importnumpyasnp1.模型实现"""inputrate_matrix:M行N列的评分矩阵,值为P*Q.P:初始化用户特征矩阵M*K.Q:初始化物品特征矩阵K*N.latent_feature_cnt:隐特征的向量个数max_iteration:最大迭代次数alpha:步长lamda:正则化系数output分解之后的P和Q"""defLFM_grad_desc(rate_matrix,l</div>
                    </li>
                    <li><a href="/article/1835466142441893888.htm"
                           title="K近邻算法_分类鸢尾花数据集" target="_blank">K近邻算法_分类鸢尾花数据集</a>
                        <span class="text-muted">_feivirus_</span>
<a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%92%8C%E6%95%B0%E5%AD%A6/1.htm">机器学习和数学</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E7%B1%BB/1.htm">分类</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/K%E8%BF%91%E9%82%BB/1.htm">K近邻</a>
                        <div>importnumpyasnpimportpandasaspdfromsklearn.datasetsimportload_irisfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportaccuracy_score1.数据预处理iris=load_iris()df=pd.DataFrame(data=ir</div>
                    </li>
                    <li><a href="/article/1835463621124124672.htm"
                           title="数据结构 | 栈和队列" target="_blank">数据结构 | 栈和队列</a>
                        <span class="text-muted">TT-Kun</span>
<a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/1.htm">数据结构与算法</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E6%A0%88/1.htm">栈</a><a class="tag" taget="_blank" href="/search/%E9%98%9F%E5%88%97/1.htm">队列</a><a class="tag" taget="_blank" href="/search/C%E8%AF%AD%E8%A8%80/1.htm">C语言</a>
                        <div>文章目录栈和队列1.栈:后进先出(LIFO)的数据结构1.1概念与结构1.2栈的实现2.队列:先进先出(FIFO)的数据结构2.1概念与结构2.2队列的实现3.栈和队列算法题3.1有效的括号3.2用队列实现栈3.3用栈实现队列3.4设计循环队列结论栈和队列在计算机科学中,栈和队列是两种基本且重要的数据结构,它们在处理数据存储和访问顺序方面有着独特的规则和应用。本文将详细介绍栈和队列的概念、结构、实</div>
                    </li>
                    <li><a href="/article/1835457443690278912.htm"
                           title="[Python] 数据结构 详解及代码" target="_blank">[Python] 数据结构 详解及代码</a>
                        <span class="text-muted">AIAdvocate</span>
<a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E9%93%BE%E8%A1%A8/1.htm">链表</a>
                        <div>今日内容大纲介绍数据结构介绍列表链表1.数据结构和算法简介程序大白话翻译,程序=数据结构+算法数据结构指的是存储,组织数据的方式.算法指的是为了解决实际业务问题而思考思路和方法,就叫:算法.2.算法的5大特性介绍算法具有独立性算法是解决问题的思路和方式,最重要的是思维,而不是语言,其(算法)可以通过多种语言进行演绎.5大特性有输入,需要传入1或者多个参数有输出,需要返回1个或者多个结果有穷性,执行</div>
                    </li>
                    <li><a href="/article/1835449249425354752.htm"
                           title="Python算法L5:贪心算法" target="_blank">Python算法L5:贪心算法</a>
                        <span class="text-muted">小熊同学哦</span>
<a class="tag" taget="_blank" href="/search/Python%E7%AE%97%E6%B3%95/1.htm">Python算法</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95/1.htm">贪心算法</a>
                        <div>Python贪心算法简介目录Python贪心算法简介贪心算法的基本步骤贪心算法的适用场景经典贪心算法问题1.**零钱兑换问题**2.**区间调度问题**3.**背包问题**贪心算法的优缺点优点:缺点:结语贪心算法(GreedyAlgorithm)是一种在每一步选择中都采取当前最优或最优解的算法。它的核心思想是,在保证每一步局部最优的情况下,希望通过贪心选择达到全局最优解。虽然贪心算法并不总能得到全</div>
                    </li>
                    <li><a href="/article/1835448111909138432.htm"
                           title="react-intl——react国际化使用方案" target="_blank">react-intl——react国际化使用方案</a>
                        <span class="text-muted">苹果酱0567</span>
<a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8E%E8%A7%A3%E6%9E%90/1.htm">面试题汇总与解析</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E9%97%B4%E4%BB%B6/1.htm">中间件</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a>
                        <div>国际化介绍i18n:internationalization国家化简称,首字母+首尾字母间隔的字母个数+尾字母,类似的还有k8s(Kubernetes)React-intl是React中最受欢迎的库。使用步骤安装#usenpmnpminstallreact-intl-D#useyarn项目入口文件配置//index.tsximportReactfrom"react";importReactDOMf</div>
                    </li>
                    <li><a href="/article/1835432106029838336.htm"
                           title="【RabbitMQ 项目】服务端:数据管理模块之绑定管理" target="_blank">【RabbitMQ 项目】服务端:数据管理模块之绑定管理</a>
                        <span class="text-muted">月夜星辉雪</span>
<a class="tag" taget="_blank" href="/search/rabbitmq/1.htm">rabbitmq</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a>
                        <div>文章目录一.编写思路二.代码实践一.编写思路定义绑定信息类交换机名称队列名称绑定关键字:交换机的路由交换算法中会用到没有是否持久化的标志,因为绑定是否持久化取决于交换机和队列是否持久化,只有它们都持久化时绑定才需要持久化。绑定就好像一根绳子,两端连接着交换机和队列,当一方不存在,它就没有存在的必要了定义绑定持久化类构造函数:如果数据库文件不存在则创建,打开数据库,创建binding_table插入</div>
                    </li>
                    <li><a href="/article/1835429201952468992.htm"
                           title="非对称加密算法原理与应用2——RSA私钥加密文件" target="_blank">非对称加密算法原理与应用2——RSA私钥加密文件</a>
                        <span class="text-muted">私语茶馆</span>
<a class="tag" taget="_blank" href="/search/%E4%BA%91%E9%83%A8%E7%BD%B2%E4%B8%8E%E5%BC%80%E5%8F%91/1.htm">云部署与开发</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E5%8F%8A%E4%BA%A7%E5%93%81%E7%81%B5%E6%84%9F%E8%AE%B0%E5%BD%95/1.htm">架构及产品灵感记录</a><a class="tag" taget="_blank" href="/search/RSA2048/1.htm">RSA2048</a><a class="tag" taget="_blank" href="/search/%E7%A7%81%E9%92%A5%E5%8A%A0%E5%AF%86/1.htm">私钥加密</a>
                        <div>作者:私语茶馆1.相关章节(1)非对称加密算法原理与应用1——秘钥的生成-CSDN博客第一章节讲述的是创建秘钥对,并将公钥和私钥导出为文件格式存储。本章节继续讲如何利用私钥加密内容,包括从密钥库或文件中读取私钥,并用RSA算法加密文件和String。2.私钥加密的概述本文主要基于第一章节的RSA2048bit的非对称加密算法讲述如何利用私钥加密文件。这种加密后的文件,只能由该私钥对应的公钥来解密。</div>
                    </li>
                    <li><a href="/article/1835429075590672384.htm"
                           title="粒子群优化 (PSO) 在三维正弦波函数中的应用" target="_blank">粒子群优化 (PSO) 在三维正弦波函数中的应用</a>
                        <span class="text-muted">subject625Ruben</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/matlab/1.htm">matlab</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a>
                        <div>在这篇博客中,我们将展示如何使用粒子群优化(PSO)算法求解三维正弦波函数,并通过增加正弦波扰动,使优化过程更加复杂和有趣。本文将介绍目标函数的定义、PSO参数设置以及算法执行的详细过程,并展示搜索空间中的动态过程和收敛曲线。1.目标函数定义我们使用的目标函数是一个三维正弦波函数,定义如下:objectiveFunc=@(x)sin(sqrt(x(1).^2+x(2).^2))+0.5*sin(5</div>
                    </li>
                    <li><a href="/article/1835420248484966400.htm"
                           title="非对称加密算法————RSA理论及详情" target="_blank">非对称加密算法————RSA理论及详情</a>
                        <span class="text-muted">hu19930613</span>

                        <div>转自:https://www.kancloud.cn/kancloud/rsa_algorithm/48484一、一点历史1976年以前,所有的加密方法都是同一种模式:(1)甲方选择某一种加密规则,对信息进行加密;(2)乙方使用同一种规则,对信息进行解密。由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法"(Symmetric-keyalgorithm)。这种加密模式有一个最大弱点</div>
                    </li>
                    <li><a href="/article/1835417718841503744.htm"
                           title="ai绘画工具midjourney怎么下载?附作品管理教程" target="_blank">ai绘画工具midjourney怎么下载?附作品管理教程</a>
                        <span class="text-muted">设计师早上好</span>

                        <div>Midjourney是一款功能强大的AI绘画工具,它使用机器学习技术和深度神经网络等算法,可以生成各种艺术风格的绘画作品。在创意设计、广告宣传等方面有着广泛的应用前景。那么,ai绘画工具midjourney怎么下载?本文将为您介绍Midjourney的下载以及作品的相关管理。一、Midjourney下载Midjourney的下载非常简单,只需打开Midjourney官网(点击“GetMidjour</div>
                    </li>
                    <li><a href="/article/1835416844375257088.htm"
                           title="【加密算法基础——对称加密和非对称加密】" target="_blank">【加密算法基础——对称加密和非对称加密】</a>
                        <span class="text-muted">XWWW668899</span>
<a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                        <div>对称加密与非对称加密对称加密和非对称加密是两种基本的加密方法,各自有不同的特点和用途。以下是详细比较:1.对称加密特点密钥:使用相同的密钥进行加密和解密。发送方和接收方必须共享这个密钥。速度:通常速度较快,适合处理大量数据。实现:算法相对简单,计算效率高。常见算法AES(高级加密标准)DES(数据加密标准)3DES(三重数据加密标准)RC4(流密码)应用场景文件加密磁盘加密传输大量数据时的加密2.</div>
                    </li>
                    <li><a href="/article/1835413694436175872.htm"
                           title="【算法练习】IDEA集成leetcode插件实现快速刷" target="_blank">【算法练习】IDEA集成leetcode插件实现快速刷</a>
                        <span class="text-muted">2401_84102892</span>
<a class="tag" taget="_blank" href="/search/2024%E5%B9%B4%E7%A8%8B%E5%BA%8F%E5%91%98%E5%AD%A6%E4%B9%A0/1.htm">2024年程序员学习</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/intellij-idea/1.htm">intellij-idea</a><a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</a>
                        <div>============点击右侧边leetcode->设置->配置地址、用户名、密码、存放目录、文件模板用户名要登录后在账号信息里看模板代码1.codefilename!velocityTool.camelC</div>
                    </li>
                    <li><a href="/article/1835409784543735808.htm"
                           title="【加密算法基础——RSA 加密】" target="_blank">【加密算法基础——RSA 加密】</a>
                        <span class="text-muted">XWWW668899</span>
<a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>RSA加密RSA(Rivest-Shamir-Adleman)加密是非对称加密,一种广泛使用的公钥加密算法,主要用于安全数据传输。公钥用于加密,私钥用于解密。RSA加密算法的名称来源于其三位发明者的姓氏:R:RonRivestS:AdiShamirA:LeonardAdleman这三位计算机科学家在1977年共同提出了这一算法,并发表了相关论文。他们的工作为公钥加密的基础奠定了重要基础,使得安全通</div>
                    </li>
                    <li><a href="/article/1835402731351797760.htm"
                           title="机器学习-聚类算法" target="_blank">机器学习-聚类算法</a>
                        <span class="text-muted">不良人龍木木</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E8%81%9A%E7%B1%BB/1.htm">聚类</a>
                        <div>机器学习-聚类算法1.AHC2.K-means3.SC4.MCL仅个人笔记,感谢点赞关注!1.AHC2.K-means3.SC传统谱聚类:个人对谱聚类算法的理解以及改进4.MCL目前仅专注于NLP的技术学习和分享感谢大家的关注与支持!</div>
                    </li>
                    <li><a href="/article/1835397055376355328.htm"
                           title="生成式地图制图" target="_blank">生成式地图制图</a>
                        <span class="text-muted">Bwywb_3</span>
<a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E7%94%9F%E6%88%90%E5%AF%B9%E6%8A%97%E7%BD%91%E7%BB%9C/1.htm">生成对抗网络</a>
                        <div>生成式地图制图(GenerativeCartography)是一种利用生成式算法和人工智能技术自动创建地图的技术。它结合了传统的地理信息系统(GIS)技术与现代生成模型(如深度学习、GANs等),能够根据输入的数据自动生成符合需求的地图。这种方法在城市规划、虚拟环境设计、游戏开发等多个领域具有应用前景。主要特点:自动化生成:通过算法和模型,系统能够根据输入的地理或空间数据自动生成地图,而无需人工逐</div>
                    </li>
                    <li><a href="/article/1835383919906746368.htm"
                           title="高性能javascript--算法和流程控制" target="_blank">高性能javascript--算法和流程控制</a>
                        <span class="text-muted">海淀萌狗</span>

                        <div>-for,while和do-while性能相当-避免使用for-in循环,==除非遍历一个属性量未知的对象==es5:for-in遍历的对象便不局限于数组,还可以遍历对象。原因:for-in每次迭代操作会同时搜索实例或者原型属性,for-in循环的每次迭代都会产生更多开销,因此要比其他循环类型慢,一般速度为其他类型循环的1/7。因此,除非明确需要迭代一个属性数量未知的对象,否则应避免使用for-i</div>
                    </li>
                    <li><a href="/article/1835383695071080448.htm"
                           title="深度 Qlearning:在直播推荐系统中的应用" target="_blank">深度 Qlearning:在直播推荐系统中的应用</a>
                        <span class="text-muted">AGI通用人工智能之禅</span>
<a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98%E6%8F%90%E5%8D%87%E8%87%AA%E6%88%91/1.htm">程序员提升自我</a><a class="tag" taget="_blank" href="/search/%E7%A1%85%E5%9F%BA%E8%AE%A1%E7%AE%97/1.htm">硅基计算</a><a class="tag" taget="_blank" href="/search/%E7%A2%B3%E5%9F%BA%E8%AE%A1%E7%AE%97/1.htm">碳基计算</a><a class="tag" taget="_blank" href="/search/%E8%AE%A4%E7%9F%A5%E8%AE%A1%E7%AE%97/1.htm">认知计算</a><a class="tag" taget="_blank" href="/search/%E7%94%9F%E7%89%A9%E8%AE%A1%E7%AE%97/1.htm">生物计算</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">神经网络</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/AIGC/1.htm">AIGC</a><a class="tag" taget="_blank" href="/search/AGI/1.htm">AGI</a><a class="tag" taget="_blank" href="/search/LLM/1.htm">LLM</a><a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/1.htm">架构设计</a><a class="tag" taget="_blank" href="/search/Agent/1.htm">Agent</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98%E5%AE%9E%E7%8E%B0%E8%B4%A2%E5%AF%8C%E8%87%AA%E7%94%B1/1.htm">程序员实现财富自由</a>
                        <div>深度Q-learning:在直播推荐系统中的应用关键词:深度Q-learning,强化学习,直播推荐系统,个性化推荐1.背景介绍1.1问题的由来随着互联网技术的飞速发展,直播平台如雨后春笋般涌现。面对海量的直播内容,用户很难快速找到自己感兴趣的内容。因此,个性化推荐系统在直播平台中扮演着越来越重要的角色。1.2研究现状目前,主流的个性化推荐算法包括协同过滤、基于内容的推荐等。这些方法在一定程度上缓</div>
                    </li>
                    <li><a href="/article/1835383403806027776.htm"
                           title="JVM源码分析之堆外内存完全解读" target="_blank">JVM源码分析之堆外内存完全解读</a>
                        <span class="text-muted">HeapDump性能社区</span>

                        <div>概述广义的堆外内存说到堆外内存,那大家肯定想到堆内内存,这也是我们大家接触最多的,我们在jvm参数里通常设置-Xmx来指定我们的堆的最大值,不过这还不是我们理解的Java堆,-Xmx的值是新生代和老生代的和的最大值,我们在jvm参数里通常还会加一个参数-XX:MaxPermSize来指定持久代的最大值,那么我们认识的Java堆的最大值其实是-Xmx和-XX:MaxPermSize的总和,在分代算法</div>
                    </li>
                    <li><a href="/article/1835376127372259328.htm"
                           title="《算法》四学习——1.1节" target="_blank">《算法》四学习——1.1节</a>
                        <span class="text-muted">进阶的Farmer</span>
<a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                        <div>前言买了一本算法4,每天看一点,对每个小结来个学习总结,输出驱动输入。本篇笔记针对第一章基础1.1基础编程模型1.1节总结了相关的语法、语言特性和书中将会用到的库。笔记自己在编码中容易遗漏的点&&优先级比||高在开发中习惯了加括号,所以没注意到这点,教材上也有但是忘记了二分查找中计算mid=left+(right-left)/2这样计算可以有效避免(left+right)/2溢出答疑java无穷大</div>
                    </li>
                                <li><a href="/article/15.htm"
                                       title="Spring4.1新特性——Spring MVC增强" target="_blank">Spring4.1新特性——Spring MVC增强</a>
                                    <span class="text-muted">jinnianshilongnian</span>
<a class="tag" taget="_blank" href="/search/spring+4.1/1.htm">spring 4.1</a>
                                    <div>目录 
Spring4.1新特性——综述 
Spring4.1新特性——Spring核心部分及其他 
Spring4.1新特性——Spring缓存框架增强 
Spring4.1新特性——异步调用和事件机制的异常处理 
Spring4.1新特性——数据库集成测试脚本初始化 
Spring4.1新特性——Spring MVC增强 
Spring4.1新特性——页面自动化测试框架Spring MVC T</div>
                                </li>
                                <li><a href="/article/142.htm"
                                       title="mysql 性能查询优化" target="_blank">mysql 性能查询优化</a>
                                    <span class="text-muted">annan211</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E4%BC%98%E5%8C%96/1.htm">优化</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a>
                                    <div>

1 时间到底花在哪了?
  mysql在执行查询的时候需要执行一系列的子任务,这些子任务包含了整个查询周期最重要的阶段,这其中包含了大量为了
  检索数据列到存储引擎的调用以及调用后的数据处理,包括排序、分组等。在完成这些任务的时候,查询需要在不同的地方
  花费时间,包括网络、cpu计算、生成统计信息和执行计划、锁等待等。尤其是向底层存储引擎检索数据的调用操作。这些调用需要在内存操</div>
                                </li>
                                <li><a href="/article/269.htm"
                                       title="windows系统配置" target="_blank">windows系统配置</a>
                                    <span class="text-muted">cherishLC</span>
<a class="tag" taget="_blank" href="/search/windows/1.htm">windows</a>
                                    <div>删除Hiberfil.sys :使用命令powercfg -h off 关闭休眠功能即可: 
http://jingyan.baidu.com/article/f3ad7d0fc0992e09c2345b51.html 
类似的还有pagefile.sys 
 
msconfig 配置启动项 
shutdown 定时关机 
 
ipconfig 查看网络配置 
ipconfig /flushdns</div>
                                </li>
                                <li><a href="/article/396.htm"
                                       title="人体的排毒时间" target="_blank">人体的排毒时间</a>
                                    <span class="text-muted">Array_06</span>
<a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C/1.htm">工作</a>
                                    <div>======================== 
||  人体的排毒时间是什么时候?|| 
========================  
 
转载于: 
http://zhidao.baidu.com/link?url=ibaGlicVslAQhVdWWVevU4TMjhiKaNBWCpZ1NS6igCQ78EkNJZFsEjCjl3T5EdXU9SaPg04bh8MbY1bR</div>
                                </li>
                                <li><a href="/article/523.htm"
                                       title="ZooKeeper" target="_blank">ZooKeeper</a>
                                    <span class="text-muted">cugfy</span>
<a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a>
                                    <div>Zookeeper是一个高性能,分布式的,开源分布式应用协调服务。它提供了简单原始的功能,分布式应用可以基于它实现更高级的服务,比如同步, 配置管理,集群管理,名空间。它被设计为易于编程,使用文件系统目录树作为数据模型。服务端跑在java上,提供java和C的客户端API。 Zookeeper是Google的Chubby一个开源的实现,是高有效和可靠的协同工作系统,Zookeeper能够用来lea</div>
                                </li>
                                <li><a href="/article/650.htm"
                                       title="网络爬虫的乱码处理" target="_blank">网络爬虫的乱码处理</a>
                                    <span class="text-muted">随意而生</span>
<a class="tag" taget="_blank" href="/search/%E7%88%AC%E8%99%AB/1.htm">爬虫</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a>
                                    <div>下边简单总结下关于网络爬虫的乱码处理。注意,这里不仅是中文乱码,还包括一些如日文、韩文 、俄文、藏文之类的乱码处理,因为他们的解决方式 是一致的,故在此统一说明。     网络爬虫,有两种选择,一是选择nutch、hetriex,二是自写爬虫,两者在处理乱码时,原理是一致的,但前者处理乱码时,要看懂源码后进行修改才可以,所以要废劲一些;而后者更自由方便,可以在编码处理</div>
                                </li>
                                <li><a href="/article/777.htm"
                                       title="Xcode常用快捷键" target="_blank">Xcode常用快捷键</a>
                                    <span class="text-muted">张亚雄</span>
<a class="tag" taget="_blank" href="/search/xcode/1.htm">xcode</a>
                                    <div>一、总结的常用命令: 
 
    隐藏xcode command+h 
 
    退出xcode command+q 
 
    关闭窗口 command+w 
 
    关闭所有窗口 command+option+w 
 
    关闭当前</div>
                                </li>
                                <li><a href="/article/904.htm"
                                       title="mongoDB索引操作" target="_blank">mongoDB索引操作</a>
                                    <span class="text-muted">adminjun</span>
<a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a><a class="tag" taget="_blank" href="/search/%E7%B4%A2%E5%BC%95/1.htm">索引</a>
                                    <div>一、索引基础:    MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧。下面是创建索引的命令:    > db.test.ensureIndex({"username":1})    可以通过下面的名称查看索引是否已经成功建立: &nbs</div>
                                </li>
                                <li><a href="/article/1031.htm"
                                       title="成都软件园实习那些话" target="_blank">成都软件园实习那些话</a>
                                    <span class="text-muted">aijuans</span>
<a class="tag" taget="_blank" href="/search/%E6%88%90%E9%83%BD+%E8%BD%AF%E4%BB%B6%E5%9B%AD+%E5%AE%9E%E4%B9%A0/1.htm">成都 软件园 实习</a>
                                    <div>无聊之中,翻了一下日志,发现上一篇经历是很久以前的事了,悔过~~ 
  断断续续离开了学校快一年了,习惯了那里一天天的幼稚、成长的环境,到这里有点与世隔绝的感觉。不过还好,那是刚到这里时的想法,现在感觉在这挺好,不管怎么样,最要感谢的还是老师能给这么好的一次催化成长的机会,在这里确实看到了好多好多能想到或想不到的东西。 
  都说在外面和学校相比最明显的差距就是与人相处比较困难,因为在外面每个人都</div>
                                </li>
                                <li><a href="/article/1158.htm"
                                       title="Linux下FTP服务器安装及配置" target="_blank">Linux下FTP服务器安装及配置</a>
                                    <span class="text-muted">ayaoxinchao</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/FTP%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">FTP服务器</a><a class="tag" taget="_blank" href="/search/vsftp/1.htm">vsftp</a>
                                    <div>检测是否安装了FTP 
[root@localhost ~]# rpm -q vsftpd 
如果未安装:package vsftpd is not installed  安装了则显示:vsftpd-2.0.5-28.el5累死的版本信息 
  
安装FTP 
运行yum install vsftpd命令,如[root@localhost ~]# yum install vsf</div>
                                </li>
                                <li><a href="/article/1285.htm"
                                       title="使用mongo-java-driver获取文档id和查找文档" target="_blank">使用mongo-java-driver获取文档id和查找文档</a>
                                    <span class="text-muted">BigBird2012</span>
<a class="tag" taget="_blank" href="/search/driver/1.htm">driver</a>
                                    <div>注:本文所有代码都使用的mongo-java-driver实现。 
  
在MongoDB中,一个集合(collection)在概念上就类似我们SQL数据库中的表(Table),这个集合包含了一系列文档(document)。一个DBObject对象表示我们想添加到集合(collection)中的一个文档(document),MongoDB会自动为我们创建的每个文档添加一个id,这个id在</div>
                                </li>
                                <li><a href="/article/1412.htm"
                                       title="JSONObject以及json串" target="_blank">JSONObject以及json串</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/JSONObject/1.htm">JSONObject</a>
                                    <div>一.JAR包简介 
    要使程序可以运行必须引入JSON-lib包,JSON-lib包同时依赖于以下的JAR包: 
    1.commons-lang-2.0.jar 
    2.commons-beanutils-1.7.0.jar 
    3.commons-collections-3.1.jar 
&n</div>
                                </li>
                                <li><a href="/article/1539.htm"
                                       title="[Zookeeper学习笔记之三]Zookeeper实例创建和会话建立的异步特性" target="_blank">[Zookeeper学习笔记之三]Zookeeper实例创建和会话建立的异步特性</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a>
                                    <div>为了说明问题,看个简单的代码, 
  
    import org.apache.zookeeper.*;  
      
    import java.io.IOException;  
    import java.util.concurrent.CountDownLatch;  
    import java.util.concurrent.ThreadLocal</div>
                                </li>
                                <li><a href="/article/1666.htm"
                                       title="【Scala十二】Scala核心六:Trait" target="_blank">【Scala十二】Scala核心六:Trait</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a>
                                    <div>Traits are a fundamental unit of code reuse in Scala. A trait encapsulates method and field definitions, which can then be reused by mixing them into classes. Unlike class inheritance, in which each c</div>
                                </li>
                                <li><a href="/article/1793.htm"
                                       title="weblogic version 10.3破解" target="_blank">weblogic version 10.3破解</a>
                                    <span class="text-muted">ronin47</span>
<a class="tag" taget="_blank" href="/search/weblogic/1.htm">weblogic</a>
                                    <div>版本:WebLogic Server 10.3 
 
说明:%DOMAIN_HOME%:指WebLogic Server 域(Domain)目录 
例如我的做测试的域的根目录 DOMAIN_HOME=D:/Weblogic/Middleware/user_projects/domains/base_domain 
 
1.为了保证操作安全,备份%DOMAIN_HOME%/security/Defa</div>
                                </li>
                                <li><a href="/article/1920.htm"
                                       title="求第n个斐波那契数" target="_blank">求第n个斐波那契数</a>
                                    <span class="text-muted">BrokenDreams</span>

                                    <div>        今天看到群友发的一个问题:写一个小程序打印第n个斐波那契数。 
        自己试了下,搞了好久。。。基础要加强了。 
        
  &nbs</div>
                                </li>
                                <li><a href="/article/2047.htm"
                                       title="读《研磨设计模式》-代码笔记-访问者模式-Visitor" target="_blank">读《研磨设计模式》-代码笔记-访问者模式-Visitor</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a>
                                    <div>声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/ 
 
 


import java.util.ArrayList;
import java.util.List;

interface IVisitor {
	
	//第二次分派,Visitor调用Element
	void visitConcret</div>
                                </li>
                                <li><a href="/article/2174.htm"
                                       title="MatConvNet的excise 3改为网络配置文件形式" target="_blank">MatConvNet的excise 3改为网络配置文件形式</a>
                                    <span class="text-muted">cherishLC</span>
<a class="tag" taget="_blank" href="/search/matlab/1.htm">matlab</a>
                                    <div>MatConvNet为vlFeat作者写的matlab下的卷积神经网络工具包,可以使用GPU。 
主页:
http://www.vlfeat.org/matconvnet/ 
教程:
http://www.robots.ox.ac.uk/~vgg/practicals/cnn/index.html 
 
注意:需要下载新版的MatConvNet替换掉教程中工具包中的matconvnet:
http</div>
                                </li>
                                <li><a href="/article/2301.htm"
                                       title="ZK Timeout再讨论" target="_blank">ZK Timeout再讨论</a>
                                    <span class="text-muted">chenchao051</span>
<a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a><a class="tag" taget="_blank" href="/search/timeout/1.htm">timeout</a><a class="tag" taget="_blank" href="/search/hbase/1.htm">hbase</a>
                                    <div>http://crazyjvm.iteye.com/blog/1693757 文中提到相关超时问题,但是又出现了一个问题,我把min和max都设置成了180000,但是仍然出现了以下的异常信息: 
Client session timed out, have not heard from server in 154339ms for sessionid 0x13a3f7732340003</div>
                                </li>
                                <li><a href="/article/2428.htm"
                                       title="CASE WHEN 用法介绍" target="_blank">CASE WHEN 用法介绍</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/group+by/1.htm">group by</a><a class="tag" taget="_blank" href="/search/case+when/1.htm">case when</a>
                                    <div>CASE WHEN 用法介绍 
 
1. CASE WHEN 表达式有两种形式 
 
 
--简单Case函数  
 
CASE sex  
WHEN '1' THEN '男'  
WHEN '2' THEN '女'  
ELSE '其他' END  
 
--Case搜索函数  
 
CASE 
WHEN sex = '1' THEN </div>
                                </li>
                                <li><a href="/article/2555.htm"
                                       title="PHP技巧汇总:提高PHP性能的53个技巧" target="_blank">PHP技巧汇总:提高PHP性能的53个技巧</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a>
                                    <div>PHP技巧汇总:提高PHP性能的53个技巧  用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,  单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的函数译注:  PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。  1、如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍</div>
                                </li>
                                <li><a href="/article/2682.htm"
                                       title="Yii框架中CGridView的使用方法以及详细示例" target="_blank">Yii框架中CGridView的使用方法以及详细示例</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/yii/1.htm">yii</a>
                                    <div>CGridView显示一个数据项的列表中的一个表。 
表中的每一行代表一个数据项的数据,和一个列通常代表一个属性的物品(一些列可能对应于复杂的表达式的属性或静态文本)。  CGridView既支持排序和分页的数据项。排序和分页可以在AJAX模式或正常的页面请求。使用CGridView的一个好处是,当用户浏览器禁用JavaScript,排序和分页自动退化普通页面请求和仍然正常运行。 
实例代码如下:</div>
                                </li>
                                <li><a href="/article/2809.htm"
                                       title="Maven项目打包成可执行Jar文件" target="_blank">Maven项目打包成可执行Jar文件</a>
                                    <span class="text-muted">dyy_gusi</span>
<a class="tag" taget="_blank" href="/search/assembly/1.htm">assembly</a>
                                    <div>Maven项目打包成可执行Jar文件 
在使用Maven完成项目以后,如果是需要打包成可执行的Jar文件,我们通过eclipse的导出很麻烦,还得指定入口文件的位置,还得说明依赖的jar包,既然都使用Maven了,很重要的一个目的就是让这些繁琐的操作简单。我们可以通过插件完成这项工作,使用assembly插件。具体使用方式如下: 
1、在项目中加入插件的依赖: 
<plugin>
	</div>
                                </li>
                                <li><a href="/article/2936.htm"
                                       title="php常见错误" target="_blank">php常见错误</a>
                                    <span class="text-muted">geeksun</span>
<a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a>
                                    <div>1.  kevent() reported that connect() failed (61: Connection refused) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastc</div>
                                </li>
                                <li><a href="/article/3063.htm"
                                       title="修改linux的用户名" target="_blank">修改linux的用户名</a>
                                    <span class="text-muted">hongtoushizi</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/change+password/1.htm">change password</a>
                                    <div>Change Linux Username 
更改Linux用户名,需要修改4个系统的文件: 
/etc/passwd 
/etc/shadow 
/etc/group 
/etc/gshadow 
古老/传统的方法是使用vi去直接修改,但是这有安全隐患(具体可自己搜一下),所以后来改成使用这些命令去代替: 
vipw 
vipw -s 
vigr 
vigr -s 
  
具体的操作顺</div>
                                </li>
                                <li><a href="/article/3190.htm"
                                       title="第五章 常用Lua开发库1-redis、mysql、http客户端" target="_blank">第五章 常用Lua开发库1-redis、mysql、http客户端</a>
                                    <span class="text-muted">jinnianshilongnian</span>
<a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/lua/1.htm">lua</a>
                                    <div>对于开发来说需要有好的生态开发库来辅助我们快速开发,而Lua中也有大多数我们需要的第三方开发库如Redis、Memcached、Mysql、Http客户端、JSON、模板引擎等。 
一些常见的Lua库可以在github上搜索,https://github.com/search?utf8=%E2%9C%93&q=lua+resty。 
  Redis客户端 
lua-resty-r</div>
                                </li>
                                <li><a href="/article/3317.htm"
                                       title="zkClient 监控机制实现" target="_blank">zkClient 监控机制实现</a>
                                    <span class="text-muted">liyonghui160com</span>
<a class="tag" taget="_blank" href="/search/zkClient+%E7%9B%91%E6%8E%A7%E6%9C%BA%E5%88%B6%E5%AE%9E%E7%8E%B0/1.htm">zkClient 监控机制实现</a>
                                    <div>  
       直接使用zk的api实现业务功能比较繁琐。因为要处理session loss,session expire等异常,在发生这些异常后进行重连。又因为ZK的watcher是一次性的,如果要基于wather实现发布/订阅模式,还要自己包装一下,将一次性订阅包装成持久订阅。另外如果要使用抽象级别更高的功能,比如分布式锁,leader选举</div>
                                </li>
                                <li><a href="/article/3444.htm"
                                       title="在Mysql 众多表中查找一个表名或者字段名的 SQL 语句" target="_blank">在Mysql 众多表中查找一个表名或者字段名的 SQL 语句</a>
                                    <span class="text-muted">pda158</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>在Mysql 众多表中查找一个表名或者字段名的 SQL 语句:   
  方法一:SELECT table_name, column_name from information_schema.columns WHERE column_name LIKE 'Name';
  方法二:SELECT column_name from information_schema.colum</div>
                                </li>
                                <li><a href="/article/3571.htm"
                                       title="程序员对英语的依赖" target="_blank">程序员对英语的依赖</a>
                                    <span class="text-muted">Smile.zeng</span>
<a class="tag" taget="_blank" href="/search/%E8%8B%B1%E8%AF%AD/1.htm">英语</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E7%8C%BF/1.htm">程序猿</a>
                                    <div>1、程序员最基本的技能,至少要能写得出代码,当我们还在为建立类的时候思考用什么单词发牢骚的时候,英语与别人的差距就直接表现出来咯。 
2、程序员最起码能认识开发工具里的英语单词,不然怎么知道使用这些开发工具。 
3、进阶一点,就是能读懂别人的代码,有利于我们学习人家的思路和技术。 
4、写的程序至少能有一定的可读性,至少要人别人能懂吧... 
 
以上一些问题,充分说明了英语对程序猿的重要性。骚年</div>
                                </li>
                                <li><a href="/article/3698.htm"
                                       title="Oracle学习笔记(8) 使用PLSQL编写触发器" target="_blank">Oracle学习笔记(8) 使用PLSQL编写触发器</a>
                                    <span class="text-muted">vipbooks</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/%E6%B4%BB%E5%8A%A8/1.htm">活动</a><a class="tag" taget="_blank" href="/search/Access/1.htm">Access</a>
                                    <div>    时间过得真快啊,转眼就到了Oracle学习笔记的最后个章节了,通过前面七章的学习大家应该对Oracle编程有了一定了了解了吧,这东东如果一段时间不用很快就会忘记了,所以我会把自己学习过的东西做好详细的笔记,用到的时候可以随时查找,马上上手!希望这些笔记能对大家有些帮助! 
    这是第八章的学习笔记,学习完第七章的子程序和包之后</div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>