Kubernetes第2天

第四章 实战入门

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

Namespace

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

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

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

Kubernetes第2天_第1张图片

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第2天_第2张图片

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><<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<span class="token operator">-</span>5ff7956ff6<span class="token operator">-</span>jj4ng   1<span class="token operator">/</span>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<span class="token operator">-</span>TO<span class="token operator">-</span>DATE   AVAILABLE   AGE
nginx   1<span class="token operator">/</span>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<span class="token operator">/</span>nginx<span class="token operator">-</span>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<span class="token operator">/</span>nginx<span class="token operator">-</span>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<span class="token operator">-</span>pod   1<span class="token operator">/</span>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<span class="token operator">-</span>pod   1<span class="token operator">/</span>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<span class="token operator">/</span>nginx<span class="token operator">-</span>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><a href="http://img.e-com-net.com/image/info8/96577169df40459d9b404375e35cd1ab.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/96577169df40459d9b404375e35cd1ab.jpg" alt="Kubernetes第2天_第3张图片" width="650" height="355" style="border:1px solid black;"></a></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<span class="token operator">/</span>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<span class="token operator">-</span>5ff7956ff6<span class="token operator">-</span>6k8cb   1<span class="token operator">/</span>1     Running   0          19s
nginx<span class="token operator">-</span>5ff7956ff6<span class="token operator">-</span>jxfjt   1<span class="token operator">/</span>1     Running   0          19s
nginx<span class="token operator">-</span>5ff7956ff6<span class="token operator">-</span>v6jqw   1<span class="token operator">/</span>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<span class="token operator">-</span>TO<span class="token operator">-</span>DATE   AVAILABLE   AGE
nginx   3<span class="token operator">/</span>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<span class="token operator">-</span>TO<span class="token operator">-</span>DATE  AVAILABLE   AGE     CONTAINERS   IMAGES              SELECTOR
nginx   3<span class="token operator">/</span>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<span class="token operator">/</span>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<span class="token operator">%</span> max unavailable<span class="token punctuation">,</span> 25<span class="token operator">%</span> 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<span class="token operator">/</span>TCP
    Host Port:    0<span class="token operator">/</span>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<span class="token operator">-</span>5ff7956ff6 <span class="token punctuation">(</span>3<span class="token operator">/</span>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>
  Normal  ScalingReplicaSet  5m43s  deployment<span class="token operator">-</span>controller  Scaled up replicaset nginx<span class="token operator">-</span>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><a href="http://img.e-com-net.com/image/info8/360d9329054f426caf4b0ddd6d0cecca.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/360d9329054f426caf4b0ddd6d0cecca.jpg" alt="Kubernetes第2天_第4张图片" width="650" height="301" style="border:1px solid black;"></a></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<span class="token operator">/</span>svc<span class="token operator">-</span>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<span class="token operator">-</span>IP       EXTERNAL<span class="token operator">-</span>IP   PORT<span class="token punctuation">(</span>S<span class="token punctuation">)</span>   AGE     SELECTOR
svc<span class="token operator">-</span>nginx1   ClusterIP   10<span class="token punctuation">.</span>109<span class="token punctuation">.</span>179<span class="token punctuation">.</span>231   <none>        80<span class="token operator">/</span>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><<span class="token operator">/</span>title>
<<span class="token operator">/</span>head>
<body>
<h1>Welcome to nginx<span class="token operator">!</span><<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<span class="token operator">/</span>svc<span class="token operator">-</span>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<span class="token operator">-</span>IP       EXTERNAL<span class="token operator">-</span>IP   PORT<span class="token punctuation">(</span>S<span class="token punctuation">)</span>        AGE    SELECTOR
svc<span class="token operator">-</span>nginx2    NodePort    10<span class="token punctuation">.</span>100<span class="token punctuation">.</span>94<span class="token punctuation">.</span>0      <none>        80:31928<span class="token operator">/</span>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<span class="token operator">/</span>
</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><a href="http://img.e-com-net.com/image/info8/aa866086f66e48739fc208fc09f773e9.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/aa866086f66e48739fc208fc09f773e9.jpg" alt="Kubernetes第2天_第5张图片" width="633" height="464" style="border:1px solid black;"></a></p> 
  <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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>base   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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>
  Normal   Scheduled  <unknown>         default<span class="token operator">-</span>scheduler  Successfully assigned dev<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>command   2<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>resources   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>resources   0<span class="token operator">/</span>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<span class="token operator">-</span>scheduler  0<span class="token operator">/</span>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><a href="http://img.e-com-net.com/image/info8/7ee2284d48c74414b290569399e396a5.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/7ee2284d48c74414b290569399e396a5.jpg" alt="Kubernetes第2天_第6张图片" width="650" height="338" style="border:1px solid black;"></a></p> 
  <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> <p><a href="http://img.e-com-net.com/image/info8/fc9422e725cf45e9bfce1aa6578c1341.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/fc9422e725cf45e9bfce1aa6578c1341.jpg" alt="Kubernetes第2天_第7张图片" width="650" height="337" style="border:1px solid black;"></a></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<span class="token operator">/</span>pod<span class="token operator">-</span>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>
  Normal  Scheduled  49s   default<span class="token operator">-</span>scheduler  Successfully assigned dev<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>initcontainer                0<span class="token operator">/</span>1     Init:0<span class="token operator">/</span>2   0          15s
pod<span class="token operator">-</span>initcontainer                0<span class="token operator">/</span>1     Init:1<span class="token operator">/</span>2   0          52s
pod<span class="token operator">-</span>initcontainer                0<span class="token operator">/</span>1     Init:1<span class="token operator">/</span>2   0          53s
pod<span class="token operator">-</span>initcontainer                0<span class="token operator">/</span>1     PodInitializing   0          89s
pod<span class="token operator">-</span>initcontainer                1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>hook<span class="token operator">-</span>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<span class="token operator">-</span>hook<span class="token operator">-</span>exec  1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>liveness<span class="token operator">-</span>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<span class="token operator">/</span>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<span class="token operator">-</span>liveness<span class="token operator">-</span>exec   0<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>liveness<span class="token operator">-</span>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<span class="token operator">-</span>scheduler  Successfully assigned dev<span class="token operator">/</span>pod<span class="token operator">-</span>liveness<span class="token operator">-</span>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<span class="token operator">-</span>liveness<span class="token operator">-</span>tcpsocket   0<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>liveness<span class="token operator">-</span>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<span class="token operator">-</span>liveness<span class="token operator">-</span>httpget   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>restartpolicy      0<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>nodename   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>nodename   0<span class="token operator">/</span>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<span class="token operator">/</span>node2 labeled
<span class="token namespace">[root@master ~]</span><span class="token comment"># kubectl label nodes node2 nodeenv=test</span>
node<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>nodeselector   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>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<span class="token operator">-</span>nodeselector   0<span class="token operator">/</span>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>
  Warning  FailedScheduling  <unknown>  default<span class="token operator">-</span>scheduler  0<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>nodeaffinity<span class="token operator">-</span>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<span class="token operator">-</span>nodeaffinity<span class="token operator">-</span>required   0<span class="token operator">/</span>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<span class="token operator">-</span>scheduler  0<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>nodeaffinity<span class="token operator">-</span>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<span class="token operator">-</span>nodeaffinity<span class="token operator">-</span>required   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>nodeaffinity<span class="token operator">-</span>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<span class="token operator">-</span>nodeaffinity<span class="token operator">-</span>preferred   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>podaffinity<span class="token operator">-</span>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<span class="token operator">-</span>podaffinity<span class="token operator">-</span>target   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>podaffinity<span class="token operator">-</span>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<span class="token operator">-</span>podaffinity<span class="token operator">-</span>required   0<span class="token operator">/</span>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>
  Warning  FailedScheduling  <unknown>  default<span class="token operator">-</span>scheduler  0<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>podaffinity<span class="token operator">-</span>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<span class="token operator">-</span>podaffinity<span class="token operator">-</span>required   1<span class="token operator">/</span>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<span class="token operator">-</span>podaffinity<span class="token operator">-</span>required 1<span class="token operator">/</span>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<span class="token operator">-</span>podaffinity<span class="token operator">-</span>target   1<span class="token operator">/</span>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<span class="token operator">/</span>pod<span class="token operator">-</span>podantiaffinity<span class="token operator">-</span>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<span class="token operator">-</span>podantiaffinity<span class="token operator">-</span>required   1<span class="token operator">/</span>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><a href="http://img.e-com-net.com/image/info8/cdac519f3a574a1fb3f3c62799711937.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/cdac519f3a574a1fb3f3c62799711937.jpg" alt="Kubernetes第2天_第8张图片" width="650" height="143" style="border:1px solid black;"></a></p> 
  <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 operator">-</span>

<span class="token comment"># 去除所有污点</span>
kubectl taint nodes node1 key<span class="token operator">-</span>
</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<span class="token operator">-</span>7665f7fd85<span class="token operator">-</span>574h4   1<span class="token operator">/</span>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<span class="token operator">-</span>7665f7fd85<span class="token operator">-</span>574h4   1<span class="token operator">/</span>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<span class="token operator">-</span>544694789<span class="token operator">-</span>6zmlf    0<span class="token operator">/</span>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<span class="token operator">-</span>7665f7fd85<span class="token operator">-</span>htkmp   0<span class="token operator">/</span>1     Pending   0          35s   <none>   <none>   <none>    
taint2<span class="token operator">-</span>544694789<span class="token operator">-</span>bn7wb    0<span class="token operator">/</span>1     Pending   0          35s   <none>   <none>   <none>     
taint3<span class="token operator">-</span>6d78dbd749<span class="token operator">-</span>tktkq   0<span class="token operator">/</span>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><a href="http://img.e-com-net.com/image/info8/cbac269daa304a95b5994703b4eb7bc6.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/cbac269daa304a95b5994703b4eb7bc6.jpg" alt="Kubernetes第2天_第9张图片" width="650" height="214" style="border:1px solid black;"></a></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<span class="token operator">-</span>toleration   0<span class="token operator">/</span>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<span class="token operator">-</span>toleration   1<span class="token operator">/</span>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> 
  <p>tag:NoSchedule-<br> [root@master ~]# kubectl taint nodes node1 tag=heima:NoExecute</p> 
  <h1>创建pod3</h1> 
  <p>[root@master ~]# kubectl run taint3 --image=nginx:1.17.1 -n dev<br> [root@master ~]# kubectl get pods -n dev -o wide<br> NAME READY STATUS RESTARTS AGE IP NODE NOMINATED<br> taint1-7665f7fd85-htkmp 0/1 Pending 0 35s <br> taint2-544694789-bn7wb 0/1 Pending 0 35s <br> taint3-6d78dbd749-tktkq 0/1 Pending 0 6s </p> 
  <pre><code>小提示:
    使用kubeadm搭建的集群,默认就会给master节点添加一个污点标记,所以pod就不会调度到master节点上.
</code></pre> 
  <p><strong>容忍(Toleration)</strong></p> 
  <p>​ 上面介绍了污点的作用,我们可以在node上添加污点用于拒绝pod调度上来,但是如果就是想将一个pod调度到一个有污点的node上去,这时候应该怎么做呢?这就要使用到<strong>容忍</strong>。</p> 
  <p>[外链图片转存中…(img-ohrhwKJP-1684326785683)]</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<span class="token operator">-</span>toleration   0<span class="token operator">/</span>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<span class="token operator">-</span>toleration   1<span class="token operator">/</span>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="1671705459150643200"></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">你可能感兴趣的:(k8s,kubernetes,docker,容器)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1835502578050363392.htm"
                           title="PHP环境搭建详细教程" target="_blank">PHP环境搭建详细教程</a>
                        <span class="text-muted">好看资源平台</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/php/1.htm">php</a>
                        <div>PHP是一个流行的服务器端脚本语言,广泛用于Web开发。为了使PHP能够在本地或服务器上运行,我们需要搭建一个合适的PHP环境。本教程将结合最新资料,介绍在不同操作系统上搭建PHP开发环境的多种方法,包括Windows、macOS和Linux系统的安装步骤,以及本地和Docker环境的配置。1.PHP环境搭建概述PHP环境的搭建主要分为以下几类:集成开发环境:例如XAMPP、WAMP、MAMP,这</div>
                    </li>
                    <li><a href="/article/1835495770502033408.htm"
                           title="Day17笔记-高阶函数" target="_blank">Day17笔记-高阶函数</a>
                        <span class="text-muted">~在杰难逃~</span>
<a class="tag" taget="_blank" href="/search/Python/1.htm">Python</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><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/pycharm/1.htm">pycharm</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/1.htm">数据分析</a>
                        <div>高阶函数【重点掌握】函数的本质:函数是一个变量,函数名是一个变量名,一个函数可以作为另一个函数的参数或返回值使用如果A函数作为B函数的参数,B函数调用完成之后,会得到一个结果,则B函数被称为高阶函数常用的高阶函数:map(),reduce(),filter(),sorted()1.map()map(func,iterable),返回值是一个iterator【容器,迭代器】func:函数iterab</div>
                    </li>
                    <li><a href="/article/1835485429059645440.htm"
                           title="docker" target="_blank">docker</a>
                        <span class="text-muted">igotyback</span>
<a class="tag" taget="_blank" href="/search/eureka/1.htm">eureka</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a>
                        <div>Docker容器的文件系统是隔离的,但是可以通过挂载卷(Volumes)或绑定挂载(BindMounts)将宿主机的文件系统目录映射到容器内部。要查看Docker容器的映射路径,可以使用以下方法:查看容器配置:使用dockerinspect命令可以查看容器的详细配置信息,包括挂载的卷。例如:bashdockerinspect在输出的JSON格式中,查找"Mounts"部分,这里会列出所有的挂载信息</div>
                    </li>
                    <li><a href="/article/1835457442260021248.htm"
                           title="ArrayList 源码解析" target="_blank">ArrayList 源码解析</a>
                        <span class="text-muted">程序猿进阶</span>
<a class="tag" taget="_blank" href="/search/Java%E5%9F%BA%E7%A1%80/1.htm">Java基础</a><a class="tag" taget="_blank" href="/search/ArrayList/1.htm">ArrayList</a><a class="tag" taget="_blank" href="/search/List/1.htm">List</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</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/idea/1.htm">idea</a>
                        <div>ArrayList是Java集合框架中的一个动态数组实现,提供了可变大小的数组功能。它继承自AbstractList并实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同步外,其余跟Vector大致相同。每个ArrayList都有一个容量capacity,表示底层数组的实际大小,容器内存储元素的个数不能多于当前容量。当向容器中添</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/1835447859219099648.htm"
                           title="06选课支付模块之基于消息队列发送支付通知消息" target="_blank">06选课支付模块之基于消息队列发送支付通知消息</a>
                        <span class="text-muted">echo 云清</span>
<a class="tag" taget="_blank" href="/search/%E5%AD%A6%E6%88%90%E5%9C%A8%E7%BA%BF/1.htm">学成在线</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/rabbitmq/1.htm">rabbitmq</a><a class="tag" taget="_blank" href="/search/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/1.htm">消息队列</a><a class="tag" taget="_blank" href="/search/%E6%94%AF%E4%BB%98%E9%80%9A%E7%9F%A5/1.htm">支付通知</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E6%88%90%E5%9C%A8%E7%BA%BF/1.htm">学成在线</a>
                        <div>消息队列发送支付通知消息需求分析订单服务作为通用服务,在订单支付成功后需要将支付结果异步通知给其他对接的微服务,微服务收到支付结果根据订单的类型去更新自己的业务数据技术方案使用消息队列进行异步通知需要保证消息的可靠性即生产端将消息成功通知到服务端:消息发送到交换机-->由交换机发送到队列-->消费者监听队列,收到消息进行处理,参考文章02-使用Docker安装RabbitMQ-CSDN博客生产者确</div>
                    </li>
                    <li><a href="/article/1835422770016645120.htm"
                           title="《 C++ 修炼全景指南:四 》揭秘 C++ List 容器背后的实现原理,带你构建自己的双向链表" target="_blank">《 C++ 修炼全景指南:四 》揭秘 C++ List 容器背后的实现原理,带你构建自己的双向链表</a>
                        <span class="text-muted">Lenyiin</span>
<a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E6%8C%87%E5%8D%97/1.htm">技术指南</a><a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/%E4%BF%AE%E7%82%BC%E5%85%A8%E6%99%AF%E6%8C%87%E5%8D%97/1.htm">修炼全景指南</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/list/1.htm">list</a><a class="tag" taget="_blank" href="/search/%E9%93%BE%E8%A1%A8/1.htm">链表</a><a class="tag" taget="_blank" href="/search/stl/1.htm">stl</a>
                        <div>本篇博客,我们将详细讲解如何从头实现一个功能齐全且强大的C++List容器,并深入到各个细节。这篇博客将包括每一步的代码实现、解释以及扩展功能的探讨,目标是让初学者也能轻松理解。一、简介1.1、背景介绍在C++中,std::list是一个基于双向链表的容器,允许高效的插入和删除操作,适用于频繁插入和删除操作的场景。与动态数组不同,list允许常数时间内的插入和删除操作,支持双向遍历。这篇文章将详细</div>
                    </li>
                    <li><a href="/article/1835408447806468096.htm"
                           title="Ubuntu18.04 Docker部署Kinship(Django)项目过程" target="_blank">Ubuntu18.04 Docker部署Kinship(Django)项目过程</a>
                        <span class="text-muted">Dante617</span>

                        <div>1Docker的安装https://blog.csdn.net/weixin_41735055/article/details/1003551792下载镜像dockerpullprogramize/python3.6.8-dlib下载的镜像里包含python3.6.8和dlib19.17.03启动镜像dockerrun-it--namekinship-p7777:80-p3307:3306-p55</div>
                    </li>
                    <li><a href="/article/1835399957885054976.htm"
                           title="docker from指令的含义_多个FROM-含义" target="_blank">docker from指令的含义_多个FROM-含义</a>
                        <span class="text-muted">weixin_39722188</span>
<a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/from%E6%8C%87%E4%BB%A4%E7%9A%84%E5%90%AB%E4%B9%89/1.htm">from指令的含义</a>
                        <div>小编典典什么是基本图片?一组文件,加上EXPOSE端口ENTRYPOINT和CMD。您可以添加文件并基于该基础图像构建新图像,Dockerfile并以FROM指令开头:后面提到的图像FROM是新图像的“基础图像”。这是否意味着如果我neo4j/neo4j在FROM指令中声明,则在运行映像时,neo数据库将自动运行并且可在端口7474的容器中使用?仅当您不覆盖CMD和时ENTRYPOINT。但是图像</div>
                    </li>
                    <li><a href="/article/1835399831116410880.htm"
                           title="Dockerfile FROM 两个" target="_blank">Dockerfile FROM 两个</a>
                        <span class="text-muted">redDelta</span>

                        <div>Docker相关视频讲解:什么是容器Docker介绍实现"DockerfileFROM两个"的步骤步骤表格步骤操作1创建一个Dockerfile文件2写入FROM指令3构建第一个镜像4创建第二个Dockerfile文件5写入FROM指令6构建第二个镜像7合并两个镜像操作步骤说明步骤1:创建一个Dockerfile文件使用任意文本编辑器创建一个名为Dockerfile的文件。登录后复制#Docker</div>
                    </li>
                    <li><a href="/article/1835395039572881408.htm"
                           title="Dockerfile命令详解之 FROM" target="_blank">Dockerfile命令详解之 FROM</a>
                        <span class="text-muted">清风怎不知意</span>
<a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8%E5%8C%96/1.htm">容器化</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>许多同学不知道Dockerfile应该如何写,不清楚Dockerfile中的指令分别有什么意义,能达到什么样的目的,接下来我将在容器化专栏中详细的为大家解释每一个指令的含义以及用法。专栏订阅传送门https://blog.csdn.net/qq_38220908/category_11989778.html指令不区分大小写。但是,按照惯例,它们应该是大写的,以便更容易地将它们与参数区分开来。(引用</div>
                    </li>
                    <li><a href="/article/1835394786899619840.htm"
                           title="Dockerfile(1) - FROM 指令详解" target="_blank">Dockerfile(1) - FROM 指令详解</a>
                        <span class="text-muted">小菠萝测试笔记</span>
<a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/cmd/1.htm">cmd</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a>
                        <div>FROM指明当前的镜像基于哪个镜像构建dockerfile必须以FROM开头,除了ARG命令可以在FROM前面FROM[--platform=][AS]FROM[--platform=][:][AS]FROM[--platform=][@][AS]小栗子FROMalpine:latest一个dockerfile可以有多个FROM可以有多个FROM来创建多个镜像,或区分构建阶段,将一个构建阶段作为另</div>
                    </li>
                    <li><a href="/article/1835379662918873088.htm"
                           title="【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(二十八)" target="_blank">【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(二十八)</a>
                        <span class="text-muted">向往风的男子</span>
<a class="tag" taget="_blank" href="/search/k8s/1.htm">k8s</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a>
                        <div>本站以分享各种运维经验和运维所需要的技能为主《python零基础入门》:python零基础入门学习《python运维脚本》:python运维脚本实践《shell》:shell学习《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战《k8》从问题中去学习k8s《docker学习》暂未更新《ceph学习》ceph日常问题解决分享《日志收集》ELK+各种中间件《运维日常》</div>
                    </li>
                    <li><a href="/article/1835379083945537536.htm"
                           title="leetcode 11. 盛最多水的容器" target="_blank">leetcode 11. 盛最多水的容器</a>
                        <span class="text-muted">Source_Chang</span>

                        <div>leetcode核心思想:双指针,数字小的那个指针移动classSolution{public:intmaxArea(vector&height){intleft=0;intright=height.size()-1;intmaxArea=0;while(left<right){maxArea=max(min(height[left],height[right])*(right-left),max</div>
                    </li>
                    <li><a href="/article/1835375621996376064.htm"
                           title="Kubernetes数据持久化" target="_blank">Kubernetes数据持久化</a>
                        <span class="text-muted">看清所苡看轻</span>
<a class="tag" taget="_blank" href="/search/kubernetes%28k8s%29/1.htm">kubernetes(k8s)</a><a class="tag" taget="_blank" href="/search/emptyDir/1.htm">emptyDir</a><a class="tag" taget="_blank" href="/search/HostPath/1.htm">HostPath</a><a class="tag" taget="_blank" href="/search/pv/1.htm">pv</a><a class="tag" taget="_blank" href="/search/pvc/1.htm">pvc</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a>
                        <div>在k8s中,Volume(数据卷)存在明确的生命周期(与包含该数据卷的容器组(pod)相同)。因此Volume的生命周期比同一容器组(pod)中任意容器的生命周期要更长,不管容器重启了多少次,数据都被保留下来。当然,如果pod不存在了,数据卷自然退出了。此时,根据pod所使用的数据卷类型不同,数据可能随着数据卷的退出而删除,也可能被真正持久化,并在下次容器组重启时仍然可以使用。从根本上来说,一个数</div>
                    </li>
                    <li><a href="/article/1835364027488890880.htm"
                           title="leetcode刷题day13|二叉树Part01(递归遍历、迭代遍历、统一迭代、层序遍历)" target="_blank">leetcode刷题day13|二叉树Part01(递归遍历、迭代遍历、统一迭代、层序遍历)</a>
                        <span class="text-muted">小冉在学习</span>
<a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</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%8C%E5%9C%BA%E5%92%8C%E5%8F%91%E5%B1%95/1.htm">职场和发展</a>
                        <div>递归遍历思路:使用递归的方式比较简单。1、递归函数的传参:因为最后输出一个数组,所以需要传入根节点和一个容器,本来想写数组,但发现长度不能确定,所以选择list。2、终止条件:当访问的节点为空时,return3、递归函数的逻辑:先访问一个节点,递归访问其他节点144.二叉树的前序遍历代码如下:classSolution{publicListpreorderTraversal(TreeNoderoo</div>
                    </li>
                    <li><a href="/article/1835361001260806144.htm"
                           title="Kubernetes部署MySQL数据持久化" target="_blank">Kubernetes部署MySQL数据持久化</a>
                        <span class="text-muted">沫殇-MS</span>
<a class="tag" taget="_blank" href="/search/Kubernetes/1.htm">Kubernetes</a><a class="tag" taget="_blank" href="/search/MySQL%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">MySQL数据库</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a>
                        <div>一、安装配置NFS服务端1、安装nfs-kernel-server:sudoapt-yinstallnfs-kernel-server2、服务端创建共享目录#列出所有可用块设备的信息lsblk#格式化磁盘sudomkfs-text4/dev/sdb#创建一个目录:sudomkdir-p/data/nfs/mysql#更改目录权限:sudochown-Rnobody:nogroup/data/nfs</div>
                    </li>
                    <li><a href="/article/1835354574077128704.htm"
                           title="Kubernetes的3种数据持久化方式" target="_blank">Kubernetes的3种数据持久化方式</a>
                        <span class="text-muted">Seal^_^</span>
<a class="tag" taget="_blank" href="/search/%E3%80%90%E4%BA%91%E5%8E%9F%E7%94%9F%E3%80%91%E5%AE%B9%E5%99%A8%E5%8C%96%E4%B8%8E%E7%BC%96%E6%8E%92%E6%8A%80%E6%9C%AF/1.htm">【云原生】容器化与编排技术</a><a class="tag" taget="_blank" href="/search/%E6%8C%81%E7%BB%AD%E9%9B%86%E6%88%90/1.htm">持续集成</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/Kubernetes/1.htm">Kubernetes</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a><a class="tag" taget="_blank" href="/search/EmptyDir/1.htm">EmptyDir</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/HostPath/1.htm">HostPath</a>
                        <div>Kubernetes的3种数据持久化方式1.EmptyDir2.HostPath3.PersistentVolume(PV)TheBegin点点关注,收藏不迷路Kubernetes提供了几种数据持久化方式,以满足不同场景的需求:1.EmptyDir用途:临时数据存储,Pod内容器间共享。特点:生命周期与Pod相同,Pod删除时数据也删除。2.HostPath用途:访问宿主机特定文件或目录。特点:增</div>
                    </li>
                    <li><a href="/article/1835353689854930944.htm"
                           title="【Kubernetes】常见面试题汇总(十一)" target="_blank">【Kubernetes】常见面试题汇总(十一)</a>
                        <span class="text-muted">summer.335</span>
<a class="tag" taget="_blank" href="/search/Kubernetes/1.htm">Kubernetes</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a>
                        <div>目录33.简述Kubernetes外部如何访问集群内的服务?34.简述Kubernetesingress?35.简述Kubernetes镜像的下载策略?33.简述Kubernetes外部如何访问集群内的服务?(1)对于Kubernetes,集群外的客户端默认情况,无法通过Pod的IP地址或者Service的虚拟IP地址:虚拟端口号进行访问。(2)通常可以通过以下方式进行访问Kubernetes集群</div>
                    </li>
                    <li><a href="/article/1835351925957160960.htm"
                           title="k8s中Service暴露的种类以及用法" target="_blank">k8s中Service暴露的种类以及用法</a>
                        <span class="text-muted">听说唐僧不吃肉</span>
<a class="tag" taget="_blank" href="/search/K8S/1.htm">K8S</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a>
                        <div>一、说明在Kubernetes中,有几种不同的方式可以将服务(Service)暴露给外部流量。这些方式通过定义服务的spec.type字段来确定。二、详解1.ClusterIP定义:默认类型,服务只能在集群内部访问。作用:通过集群内部IP地址暴露服务。示例:spec:type:ClusterIPports:-port:80targetPo</div>
                    </li>
                    <li><a href="/article/1835349023540736000.htm"
                           title="二十四、k8s 资源管理" target="_blank">二十四、k8s 资源管理</a>
                        <span class="text-muted">繁华依在</span>
<a class="tag" taget="_blank" href="/search/k8s/1.htm">k8s</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a>
                        <div>目录一、资源配置范围管理LimitRange介绍1、LimitRange可以做什么:2、资源限制和请求的约束3、创建LimitsRange对象4、示例:创建一个pod5、测试用例测试1:测试2:测试3:二、资源服务质量管理(RequestsQos)1、Qos级别分类:1.1、Guaranteed:1.2、BestEffort:1.3、Burstable:2、Qos的工作特点3、示例三、资源配额管理</div>
                    </li>
                    <li><a href="/article/1835347257772306432.htm"
                           title="Kubernetes 自定义控制器开发" target="_blank">Kubernetes 自定义控制器开发</a>
                        <span class="text-muted">IT回忆录</span>
<a class="tag" taget="_blank" href="/search/Kubenetes/1.htm">Kubenetes</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a>
                        <div>目录前言一、CRD二、创建数据库表(Mysql)二、控制器开发1.使用kubernetes的examplecontroller模板2.在controller.go中新增数据表监听方法3.修改tools工具生成资源对象结构体定义这里记录开发k8s控制器的一般方式,controller开发主要使用k8s提供的client-go库进行。前言Controller监听集群内部资源对象的变化,编辑资源对象(增</div>
                    </li>
                    <li><a href="/article/1835344356878413824.htm"
                           title="用kubedam搭建的k8s证书过期处理方法" target="_blank">用kubedam搭建的k8s证书过期处理方法</a>
                        <span class="text-muted">我滴鬼鬼呀wks</span>
<a class="tag" taget="_blank" href="/search/k8s/1.htm">k8s</a><a class="tag" taget="_blank" href="/search/1024%E7%A8%8B%E5%BA%8F%E5%91%98%E8%8A%82/1.htm">1024程序员节</a>
                        <div>kubeadm部署的k8s证书过期1、查看证书过期时间kubeadmalphacertscheck-expiration若证书已经过期无法试用kubectl命令建议修改服务器时间到未过期的时间段2、配置kube-controller-manager.yaml文件cat/etc/kubernetes/manifests/kube-controller-manager.yamlapiVersion:v</div>
                    </li>
                    <li><a href="/article/1835340955637608448.htm"
                           title="k8s证书过期问题处理" target="_blank">k8s证书过期问题处理</a>
                        <span class="text-muted">olina_qin</span>
<a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a>
                        <div>k8s证书过期问题处理opensslx509-in/etc/kubernetes/pki/apiserver.crt-noout-dateskubeadmcertsrenewallsystemctlrestartkubeleopensslx509-in/etc/kubernetes/pki/apiserver.crt-noout-text|grep"NotAfter"cp/etc/kubernet</div>
                    </li>
                    <li><a href="/article/1835337301350248448.htm"
                           title="Kubernetes Ingress 控制器(Nginx)安装与使用教程" target="_blank">Kubernetes Ingress 控制器(Nginx)安装与使用教程</a>
                        <span class="text-muted">农优影</span>

                        <div>KubernetesIngress控制器(Nginx)安装与使用教程kubernetes-ingressNGINXandNGINXPlusIngressControllersforKubernetes项目地址:https://gitcode.com/gh_mirrors/ku/kubernetes-ingress1.项目目录结构及介绍在nginxinc/kubernetes-ingress仓库中,</div>
                    </li>
                    <li><a href="/article/1835331377520799744.htm"
                           title="【K8s】专题十一:Kubernetes 集群证书过期处理方法" target="_blank">【K8s】专题十一:Kubernetes 集群证书过期处理方法</a>
                        <span class="text-muted">行者Sun1989</span>
<a class="tag" taget="_blank" href="/search/Kubernetes/1.htm">Kubernetes</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a>
                        <div>本文内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发、订阅专栏!专栏订阅入口Linux专栏|Docker专栏|Kubernetes专栏往期精彩文章【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决方法【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决方法(续)【Docker】MySQL源码构建Docker镜</div>
                    </li>
                    <li><a href="/article/1835310380474265600.htm"
                           title="Java面试笔记记录6" target="_blank">Java面试笔记记录6</a>
                        <span class="text-muted">今天背八股了吗</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                        <div>1.Spring是什么?特性?有哪些模块?Spring是一个轻量级、非入侵式的控制反转Ioc和面向切面AOP的框架。特性:1.Ioc和DISpring的核心就是一个大的工厂容器,可以维护所有对象的创建和依赖关系,Spring工厂用于生成Bean,并且管理Bean的生命周期,实现高内聚低耦合的设计理念。2.AOP编程Spring提供面向切面编程,可以方便实现对程序进行权限拦截、运行监控等切面功能。3</div>
                    </li>
                    <li><a href="/article/1835269935358636032.htm"
                           title="Docker学习十一:Kubernetes概述" target="_blank">Docker学习十一:Kubernetes概述</a>
                        <span class="text-muted">爱打羽球的程序猿</span>
<a class="tag" taget="_blank" href="/search/Docker%E5%AD%A6%E4%B9%A0%E7%B3%BB%E5%88%97/1.htm">Docker学习系列</a><a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a>
                        <div>一、Kubernetes简介2006年,Google提出了云计算的概念,当时的云计算领域还是以虚拟机为代表的云平台。2013年,Docker横空出世,Docker提出了镜像、仓库等核心概念,规范了服务的交付标准,使得复杂服务的落地变得更加简单,之后Docker又定义了OCI标准,Docker在容器领域称为事实的标准。但是,Docker诞生只是帮助定义了开发和交付标准,如果想要在生产环境中大批量的使</div>
                    </li>
                    <li><a href="/article/1835269304761806848.htm"
                           title="Cloud Native Weekly | 华为云抢先发布Redis5.0,红帽宣布收购混合云提供商" target="_blank">Cloud Native Weekly | 华为云抢先发布Redis5.0,红帽宣布收购混合云提供商</a>
                        <span class="text-muted">weixin_34302561</span>
<a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/devops/1.htm">devops</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a>
                        <div>1——华为云抢先发布Redis5.02——DigitalOceanK8s服务正式上线3——红帽宣布收购混合云提供商NooBaa4——微软发布多项AzureKubernetes服务更新1华为云抢先发布Redis5.012月17日,华为云在DCS2.0的基础上,快人一步,抢先推出了新的Redis5.0产品,这是一个崭新的突破。目前国内在缓存领域的发展普遍停留在Redis4.0阶段,华为云率先发布了Re</div>
                    </li>
                    <li><a href="/article/1835267918531751936.htm"
                           title="安装 `privoxy` 将 Socks5 转换为 HTTP 代理" target="_blank">安装 `privoxy` 将 Socks5 转换为 HTTP 代理</a>
                        <span class="text-muted">MonkeyKing.sun</span>
<a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a>
                        <div>(base)shgbitai@shgbitai-C9X299-PGF:~/tools$curl-xhttp://127.0.0.1:1080https://registry-1.docker.io/v2/curl:(56)ProxyCONNECTaborted(base)shgbitai@shgbitai-C9X299-PGF:~/tools$curl-xhttps://127.0.0.1:108</div>
                    </li>
                                <li><a href="/article/51.htm"
                                       title="mondb入手" target="_blank">mondb入手</a>
                                    <span class="text-muted">木zi_鸣</span>
<a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a>
                                    <div>windows 启动mongodb  编写bat文件, 
 
mongod --dbpath D:\software\MongoDBDATA 
mongod --help  查询各种配置 
配置在mongob 
 
打开批处理,即可启动,27017原生端口,shell操作监控端口  扩展28017,web端操作端口 
 
启动配置文件配置, 
 
数据更灵活 </div>
                                </li>
                                <li><a href="/article/178.htm"
                                       title="大型高并发高负载网站的系统架构" target="_blank">大型高并发高负载网站的系统架构</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/%E9%AB%98%E5%B9%B6%E5%8F%91/1.htm">高并发</a><a class="tag" taget="_blank" href="/search/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/1.htm">负载均衡</a>
                                    <div>        扩展Web应用程序 
一.概念 
        简单的来说,如果一个系统可扩展,那么你可以通过扩展来提供系统的性能。这代表着系统能够容纳更高的负载、更大的数据集,并且系统是可维护的。扩展和语言、某项具体的技术都是无关的。扩展可以分为两种: 
        1.</div>
                                </li>
                                <li><a href="/article/305.htm"
                                       title="DISPLAY变量和xhost(原创)" target="_blank">DISPLAY变量和xhost(原创)</a>
                                    <span class="text-muted">czmmiao</span>
<a class="tag" taget="_blank" href="/search/display/1.htm">display</a>
                                    <div>DISPLAY 
在Linux/Unix类操作系统上, DISPLAY用来设置将图形显示到何处. 直接登陆图形界面或者登陆命令行界面后使用startx启动图形, DISPLAY环境变量将自动设置为:0:0, 此时可以打开终端, 输出图形程序的名称(比如xclock)来启动程序, 图形将显示在本地窗口上, 在终端上输入printenv查看当前环境变量, 输出结果中有如下内容:DISPLAY=:0.0</div>
                                </li>
                                <li><a href="/article/432.htm"
                                       title="获取B/S客户端IP" target="_blank">获取B/S客户端IP</a>
                                    <span class="text-muted">周凡杨</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/jsp/1.htm">jsp</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/%E6%B5%8F%E8%A7%88%E5%99%A8/1.htm">浏览器</a>
                                    <div>   最近想写个B/S架构的聊天系统,因为以前做过C/S架构的QQ聊天系统,所以对于Socket通信编程只是一个巩固。对于C/S架构的聊天系统,由于存在客户端Java应用,所以直接在代码中获取客户端的IP,应用的方法为: 
   String ip = InetAddress.getLocalHost().getHostAddress(); 
然而对于WEB</div>
                                </li>
                                <li><a href="/article/559.htm"
                                       title="浅谈类和对象" target="_blank">浅谈类和对象</a>
                                    <span class="text-muted">朱辉辉33</span>
<a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a>
                                    <div>    类是对一类事物的总称,对象是描述一个物体的特征,类是对象的抽象。简单来说,类是抽象的,不占用内存,对象是具体的, 
占用存储空间。 
    类是由属性和方法构成的,基本格式是public  class 类名{ 
 
 //定义属性 
 private/public 数据类型 属性名; 
 
 //定义方法 
 publ</div>
                                </li>
                                <li><a href="/article/686.htm"
                                       title="android activity与viewpager+fragment的生命周期问题" target="_blank">android activity与viewpager+fragment的生命周期问题</a>
                                    <span class="text-muted">肆无忌惮_</span>
<a class="tag" taget="_blank" href="/search/viewpager/1.htm">viewpager</a>
                                    <div>有一个Activity里面是ViewPager,ViewPager里面放了两个Fragment。 
第一次进入这个Activity。开启了服务,并在onResume方法中绑定服务后,对Service进行了一定的初始化,其中调用了Fragment中的一个属性。 
		super.onResume();
		bindService(intent, conn, BIND_AUTO_CREATE);
</div>
                                </li>
                                <li><a href="/article/813.htm"
                                       title="base64Encode对图片进行编码" target="_blank">base64Encode对图片进行编码</a>
                                    <span class="text-muted">843977358</span>
<a class="tag" taget="_blank" href="/search/base64/1.htm">base64</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E7%89%87/1.htm">图片</a><a class="tag" taget="_blank" href="/search/encoder/1.htm">encoder</a>
                                    <div>/**
	 * 对图片进行base64encoder编码
	 * 
	 * @author mrZhang
	 * @param path
	 * @return
	 */
	public static String encodeImage(String path) {
		BASE64Encoder encoder = null;
		byte[] b = null;
		I</div>
                                </li>
                                <li><a href="/article/940.htm"
                                       title="Request Header简介" target="_blank">Request Header简介</a>
                                    <span class="text-muted">aigo</span>
<a class="tag" taget="_blank" href="/search/servlet/1.htm">servlet</a>
                                    <div>当一个客户端(通常是浏览器)向Web服务器发送一个请求是,它要发送一个请求的命令行,一般是GET或POST命令,当发送POST命令时,它还必须向服务器发送一个叫“Content-Length”的请求头(Request   Header)   用以指明请求数据的长度,除了Content-Length之外,它还可以向服务器发送其它一些Headers,如:    </div>
                                </li>
                                <li><a href="/article/1067.htm"
                                       title="HttpClient4.3 创建SSL协议的HttpClient对象" target="_blank">HttpClient4.3 创建SSL协议的HttpClient对象</a>
                                    <span class="text-muted">alleni123</span>
<a class="tag" taget="_blank" href="/search/httpclient/1.htm">httpclient</a><a class="tag" taget="_blank" href="/search/%E7%88%AC%E8%99%AB/1.htm">爬虫</a><a class="tag" taget="_blank" href="/search/ssl/1.htm">ssl</a>
                                    <div>public class HttpClientUtils
{
	public static CloseableHttpClient createSSLClientDefault(CookieStore cookies){
		SSLContext sslContext=null;
		
		try
		{
			sslContext=new SSLContextBuilder().l</div>
                                </li>
                                <li><a href="/article/1194.htm"
                                       title="java取反 -右移-左移-无符号右移的探讨" target="_blank">java取反 -右移-左移-无符号右移的探讨</a>
                                    <span class="text-muted">百合不是茶</span>
<a class="tag" taget="_blank" href="/search/%E4%BD%8D%E8%BF%90%E7%AE%97%E7%AC%A6+%E4%BD%8D%E7%A7%BB/1.htm">位运算符 位移</a>
                                    <div>取反:
		在二进制中第一位,1表示符数,0表示正数
		byte a = -1;
		原码:10000001
		反码:11111110
		补码:11111111
      //异或: 00000000
		byte b = -2;
		原码:10000010
		反码:11111101
		补码:11111110
      //异或: 00000001
		
	</div>
                                </li>
                                <li><a href="/article/1321.htm"
                                       title="java多线程join的作用与用法" target="_blank">java多线程join的作用与用法</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%A4%9A%E7%BA%BF%E7%A8%8B/1.htm">多线程</a>
                                    <div>        对于JAVA的join,JDK 是这样说的:join public final void join (long millis )throws InterruptedException Waits at most millis milliseconds for this thread to die. A timeout of 0 means t</div>
                                </li>
                                <li><a href="/article/1448.htm"
                                       title="Java发送http请求(get 与post方法请求)" target="_blank">Java发送http请求(get 与post方法请求)</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a>
                                    <div>PostRequest.java 
package com.bijian.study;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURL</div>
                                </li>
                                <li><a href="/article/1575.htm"
                                       title="【Struts2二】struts.xml中package下的action配置项默认值" target="_blank">【Struts2二】struts.xml中package下的action配置项默认值</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/struts.xml/1.htm">struts.xml</a>
                                    <div>在第一部份,定义了struts.xml文件,如下所示: 
  
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts</div>
                                </li>
                                <li><a href="/article/1702.htm"
                                       title="【Kafka十三】Kafka Simple Consumer" target="_blank">【Kafka十三】Kafka Simple Consumer</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/simple/1.htm">simple</a>
                                    <div>代码中关于Host和Port是割裂开的,这会导致单机环境下的伪分布式Kafka集群环境下,这个例子没法运行。 
实际情况是需要将host和port绑定到一起, 
  
package kafka.examples.lowlevel;

import kafka.api.FetchRequest;
import kafka.api.FetchRequestBuilder;
impo</div>
                                </li>
                                <li><a href="/article/1829.htm"
                                       title="nodejs学习api" target="_blank">nodejs学习api</a>
                                    <span class="text-muted">ronin47</span>
<a class="tag" taget="_blank" href="/search/nodejs+api/1.htm">nodejs api</a>
                                    <div>NodeJS基础 什么是NodeJS 
JS是脚本语言,脚本语言都需要一个解析器才能运行。对于写在HTML页面里的JS,浏览器充当了解析器的角色。而对于需要独立运行的JS,NodeJS就是一个解析器。 
每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许JS使用运行环境提供的内置对象和方法做一些事情。例如运行在浏览器中的JS的用途是操作DOM,浏览器就提供了docum</div>
                                </li>
                                <li><a href="/article/1956.htm"
                                       title="java-64.寻找第N个丑数" target="_blank">java-64.寻找第N个丑数</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>


public class UglyNumber {

	/**
	 * 64.查找第N个丑数
具体思路可参考 [url] http://zhedahht.blog.163.com/blog/static/2541117420094245366965/[/url]
	 * 
题目:我们把只包含因子
2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14</div>
                                </li>
                                <li><a href="/article/2083.htm"
                                       title="二维数组(矩阵)对角线输出" target="_blank">二维数组(矩阵)对角线输出</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84/1.htm">二维数组</a>
                                    <div>

/**
二维数组 对角线输出 两个方向
例如对于数组:
{ 1, 2, 3, 4 }, 
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }, 
{ 13, 14, 15, 16 },

slash方向输出:
1 
5 2 
9 6 3 
13 10 7 4 
14 11 8 
15 12 
16 

backslash输出:
4 
3</div>
                                </li>
                                <li><a href="/article/2210.htm"
                                       title="[JWFD开源工作流设计]工作流跳跃模式开发关键点(今日更新)" target="_blank">[JWFD开源工作流设计]工作流跳跃模式开发关键点(今日更新)</a>
                                    <span class="text-muted">comsci</span>
<a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C%E6%B5%81/1.htm">工作流</a>
                                    <div>   既然是做开源软件的,我们的宗旨就是给大家分享设计和代码,那么现在我就用很简单扼要的语言来透露这个跳跃模式的设计原理 
 
   大家如果用过JWFD的ARC-自动运行控制器,或者看过代码,应该知道在ARC算法模块中有一个函数叫做SAN(),这个函数就是ARC的核心控制器,要实现跳跃模式,在SAN函数中一定要对LN链表数据结构进行操作,首先写一段代码,把</div>
                                </li>
                                <li><a href="/article/2337.htm"
                                       title="redis常见使用" target="_blank">redis常见使用</a>
                                    <span class="text-muted">cuityang</span>
<a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/%E5%B8%B8%E8%A7%81%E4%BD%BF%E7%94%A8/1.htm">常见使用</a>
                                    <div>redis 通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings、map、 list、sets、 sorted sets 
 
引入jar包 jedis-2.1.0.jar  (本文下方提供下载) 
 
package redistest; 
 
import redis.clients.jedis.Jedis; 
 
public class Listtest</div>
                                </li>
                                <li><a href="/article/2464.htm"
                                       title="配置多个redis" target="_blank">配置多个redis</a>
                                    <span class="text-muted">dalan_123</span>
<a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a>
                                    <div>配置多个redis客户端 
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi=&quo</div>
                                </li>
                                <li><a href="/article/2591.htm"
                                       title="attrib命令" target="_blank">attrib命令</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/attr/1.htm">attr</a>
                                    <div>     
attrib指令用于修改文件的属性.文件的常见属性有:只读.存档.隐藏和系统.      
  只读属性是指文件只可以做读的操作.不能对文件进行写的操作.就是文件的写保护.  
 
  存档属性是用来标记文件改动的.即在上一次备份后文件有所改动.一些备份软件在备份的时候会只去备份带有存档属性的文件.  
 </div>
                                </li>
                                <li><a href="/article/2718.htm"
                                       title="Yii使用公共函数" target="_blank">Yii使用公共函数</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/yii/1.htm">yii</a>
                                    <div>在网站项目中,没必要把公用的函数写成一个工具类,有时候面向过程其实更方便。   在入口文件index.php里添加   require_once('protected/function.php');   即可对其引用,成为公用的函数集合。   function.php如下:   
   <?php   /**     * This is the shortcut to D</div>
                                </li>
                                <li><a href="/article/2845.htm"
                                       title="linux 系统资源的查看(free、uname、uptime、netstat)" target="_blank">linux 系统资源的查看(free、uname、uptime、netstat)</a>
                                    <span class="text-muted">eksliang</span>
<a class="tag" taget="_blank" href="/search/netstat/1.htm">netstat</a><a class="tag" taget="_blank" href="/search/linux+uname/1.htm">linux uname</a><a class="tag" taget="_blank" href="/search/linux+uptime/1.htm">linux uptime</a><a class="tag" taget="_blank" href="/search/linux+free/1.htm">linux free</a>
                                    <div>linux 系统资源的查看 
转载请出自出处:http://eksliang.iteye.com/blog/2167081 
  
http://eksliang.iteye.com 一、free查看内存的使用情况 
语法如下: 
  
free [-b][-k][-m][-g] [-t]
参数含义
-b:直接输入free时,显示的单位是kb我们可以使用b(bytes),m</div>
                                </li>
                                <li><a href="/article/2972.htm"
                                       title="JAVA的位操作符" target="_blank">JAVA的位操作符</a>
                                    <span class="text-muted">greemranqq</span>
<a class="tag" taget="_blank" href="/search/%E4%BD%8D%E8%BF%90%E7%AE%97/1.htm">位运算</a><a class="tag" taget="_blank" href="/search/JAVA%E4%BD%8D%E7%A7%BB/1.htm">JAVA位移</a><a class="tag" taget="_blank" href="/search/%3C%3C/1.htm"><<</a><a class="tag" taget="_blank" href="/search/%3E%3E%3E/1.htm">>>></a>
                                    <div>最近几种进制,加上各种位操作符,发现都比较模糊,不能完全掌握,这里就再熟悉熟悉。 
  
1.按位操作符 : 
   按位操作符是用来操作基本数据类型中的单个bit,即二进制位,会对两个参数执行布尔代数运算,获得结果。 
   与(&)运算: 
   1&1 = 1, 1&0 = 0, 0&0 &</div>
                                </li>
                                <li><a href="/article/3099.htm"
                                       title="Web前段学习网站" target="_blank">Web前段学习网站</a>
                                    <span class="text-muted">ihuning</span>
<a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a>
                                    <div>  
Web前段学习网站 
菜鸟学习:http://www.w3cschool.cc/ 
  
JQuery中文网:http://www.jquerycn.cn/ 
  
内存溢出:http://outofmemory.cn/#csdn.blog 
  
http://www.icoolxue.com/ 
  
http://www.jikexue</div>
                                </li>
                                <li><a href="/article/3226.htm"
                                       title="强强联合:FluxBB 作者加盟 Flarum" target="_blank">强强联合:FluxBB 作者加盟 Flarum</a>
                                    <span class="text-muted">justjavac</span>
<a class="tag" taget="_blank" href="/search/r/1.htm">r</a>
                                    <div>原文:FluxBB Joins Forces With Flarum作者:Toby Zerner译文:强强联合:FluxBB 作者加盟 Flarum译者:justjavac  
FluxBB 是一个快速、轻量级论坛软件,它的开发者是一名德国的 PHP 天才 Franz Liedke。FluxBB 的下一个版本(2.0)将被完全重写,并已经开发了一段时间。FluxBB 看起来非常有前途的,</div>
                                </li>
                                <li><a href="/article/3353.htm"
                                       title="java统计在线人数(session存储信息的)" target="_blank">java统计在线人数(session存储信息的)</a>
                                    <span class="text-muted">macroli</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a>
                                    <div>这篇日志是我写的第三次了 前两次都发布失败!郁闷极了! 
  
由于在web开发中常常用到这一部分所以在此记录一下,呵呵,就到备忘录了! 
我对于登录信息时使用session存储的,所以我这里是通过实现HttpSessionAttributeListener这个接口完成的。 
1、实现接口类,在web.xml文件中配置监听类,从而可以使该类完成其工作。 
public class Ses</div>
                                </li>
                                <li><a href="/article/3480.htm"
                                       title="bootstrp carousel初体验 快速构建图片播放" target="_blank">bootstrp carousel初体验 快速构建图片播放</a>
                                    <span class="text-muted">qiaolevip</span>
<a class="tag" taget="_blank" href="/search/%E6%AF%8F%E5%A4%A9%E8%BF%9B%E6%AD%A5%E4%B8%80%E7%82%B9%E7%82%B9/1.htm">每天进步一点点</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83/1.htm">学习永无止境</a><a class="tag" taget="_blank" href="/search/bootstrap/1.htm">bootstrap</a><a class="tag" taget="_blank" href="/search/%E7%BA%B5%E8%A7%82%E5%8D%83%E8%B1%A1/1.htm">纵观千象</a>
                                    <div>img{
			border: 1px solid white;
			box-shadow: 2px 2px 12px #333;
			_width: expression(this.width > 600 ? "600px" : this.width + "px");
			_height: expression(this.width &</div>
                                </li>
                                <li><a href="/article/3607.htm"
                                       title="SparkSQL读取HBase数据,通过自定义外部数据源" target="_blank">SparkSQL读取HBase数据,通过自定义外部数据源</a>
                                    <span class="text-muted">superlxw1234</span>
<a class="tag" taget="_blank" href="/search/spark/1.htm">spark</a><a class="tag" taget="_blank" href="/search/sparksql/1.htm">sparksql</a><a class="tag" taget="_blank" href="/search/sparksql%E8%AF%BB%E5%8F%96hbase/1.htm">sparksql读取hbase</a><a class="tag" taget="_blank" href="/search/sparksql%E5%A4%96%E9%83%A8%E6%95%B0%E6%8D%AE%E6%BA%90/1.htm">sparksql外部数据源</a>
                                    <div>关键字:SparkSQL读取HBase、SparkSQL自定义外部数据源 
  
  
前面文章介绍了SparSQL通过Hive操作HBase表。 
  
SparkSQL从1.2开始支持自定义外部数据源(External DataSource),这样就可以通过API接口来实现自己的外部数据源。这里基于Spark1.4.0,简单介绍SparkSQL自定义外部数据源,访</div>
                                </li>
                                <li><a href="/article/3734.htm"
                                       title="Spring Boot 1.3.0.M1发布" target="_blank">Spring Boot 1.3.0.M1发布</a>
                                    <span class="text-muted">wiselyman</span>
<a class="tag" taget="_blank" href="/search/spring+boot/1.htm">spring boot</a>
                                    <div>    Spring Boot 1.3.0.M1于6.12日发布,现在可以从Spring milestone repository下载。这个版本是基于Spring Framework 4.2.0.RC1,并在Spring Boot 1.2之上提供了大量的新特性improvements and new features。主要包含以下: 
  
1.提供一个新的sprin</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>