anchor.diff:  10.200.10.16 k8s4
   EOF
   ----
  +
  +[[podAssignment]]
  +==== pod的调度
  +TIP: 此处简单说明pod的调度配置，方便后文中各组件的安装配置时的参考。
  +     更详细的配置细节请参考以下官方文档：
  +     https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
  +     https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
  +
  +===== node亲和性和调度
  +.nodeName
  +nodeName是最简单的pod节点选择的方法，直接根据节点的名字来选择pod要调度的节点：
  +[source,yaml]
  +----
  +apiVersion: v1
  +kind: Pod
  +metadata:
  +  name: nginx
  +spec:
  +  containers:
  +  - name: nginx
  +    image: nginx
  +  nodeName: devops
  +----
  +
  +.nodeSelector
  +使用此功能需要先给要被调度的node加上标签： +
  +`kubectl label nodes <node-name> <label-key>=<label-value>` +
  +eg: +
  +`kubectl label nodes devops tag=devops`
  +
  +查看node的标签： +
  +`kubectl get nodes --show-labels`
  +
  +给pod添加nodeSelector（推荐在controller部分加，eg:Deployment,StatefulSet等）
  +[source,yaml]
  +----
  +spec:
  +  containers:
  +  - name: nginx
  +    image: nginx
  +    imagePullPolicy: IfNotPresent
  +  nodeSelector:
  +    tag: devops
  +----
  +移除标签：
  +`kubectl label nodes devops tag-`
  +
  +
  +.Tolerations
  +给node添加污点： +
  +`kubectl taint nodes devops key=value:NoSchedule`
  +给pod添加tolerations：
  +[source,yaml]
  +----
  +tolerations:
  +- key: "key"
  +  operator: "Equal"
  +  value: "value"
  +  effect: "NoSchedule"
  +----
  +以上配置是指：当node满足pod的tolerations的条件 `key=value:NoSchedule` 时，pod才会被调度到该节点上。
  +
  +移除node的污点： +
  +`kubectl taint nodes devops key:NoSchedule-`
  +
  +.node的亲和性和反亲和性
  +eg:
  +[source,bash]
  +----
  +kubectl label nodes k8s1 devops=1
  +kubectl label nodes k8s2 devops=2
  +kubectl label nodes k8s3 devops=3
  +----
  +
  +[source,yaml]
  +----
  +spec:
  +  affinity:
  +    nodeAffinity:
  +      requiredDuringSchedulingIgnoredDuringExecution:
  +        nodeSelectorTerms:
  +        - matchExpressions:
  +          - key: devops
  +            operator: In
  +            values:
  +            - 1
  +            - 2
  +      preferredDuringSchedulingIgnoredDuringExecution:
  +      - weight: 1
  +        preference:
  +          matchExpressions:
  +          - key: devops
  +            operator: In
  +            values:
  +            - 3
  +----
  +以上例子说明，pod将会被调度到打有 `devops=1` 和 `devops=2` 标签的节点上去， `devops=3`的节点为备选节点。 +
  +operator的值可以为：`In, NotIn, Exists, DoesNotExist, Gt, Lt.` +
  +此外，可以通过给 `operator`设值 `NotIn` 或 `DoesNotExist`，来实现node的反亲和性功能。
  +
  +===== pod亲和性与反亲和性调度
  +.Inter-pod affinity and anti-affinity
  +[source,yaml]
  +----
  +spec:
  +  affinity:
  +    podAffinity:
  +      requiredDuringSchedulingIgnoredDuringExecution:
  +      - labelSelector:
  +          matchExpressions:
  +          - key: security
  +            operator: In
  +            values:
  +            - S1
  +        topologyKey: failure-domain.beta.kubernetes.io/zone
  +    podAntiAffinity:
  +      preferredDuringSchedulingIgnoredDuringExecution:
  +      - weight: 100
  +        podAffinityTerm:
  +          labelSelector:
  +            matchExpressions:
  +            - key: security
  +              operator: In
  +              values:
  +              - S2
  +          topologyKey: kubernetes.io/hostname
  +----
  +
  +pod的亲和性调度，主要是根据pod及node的标签来进行调度的。 +
  +当一个节点上已有至少一个正在运行的，并带有满足该pod的podAffinity条件的标签的pod1、且该节点有`failure-domain.beta.kubernetes.io/zone`的标签，则该pod会被调度到pod1的节点上去。 +
  +反亲和性与之相反，当某一节点上至少有一个正在运行的、具有满足podAntiAffinity条件的pod2，则该pod不会被调度到pod2的节点上去。
   
   
   ==== docker
  
positive.code: 
  ==== elasticsearch
  
  TIP: https://github.com/helm/charts/tree/master/stable/elasticsearch
  
  [source,bash]
  ----
  # TBD 使用PVC
  
  helm install --name dew-elasticsearch stable/elasticsearch --namespace devops \
      --set image.tag="6.6.1" \
      --set cluster.name=dew-elasticsearch \
      --set client.ingress.enabled=true \
      --set client.ingress.user=elasticsearch \
      --set client.ingress.password=Dew\!123456 \
      --set client.ingress.hosts={es.dew.ms} \
      --set master.exposeHttp=true \
      --set master.persistence.enabled=true \
      --set master.persistence.size=200Gi \
      --set data.exposeHttp=true \
      --set data.persistence.enabled=true \
      --set data.persistence.size=200Gi
  ----
  
  ==== kibana
  
  
negative.code: 
  [source,bash]
  ----
  
  # 在NFS服务器上加上文件路径,并创建需要的目录
  
  vi /etc/exports
  
  /data/nfs/kibana    *(rw,sync,no_root_squash,no_all_squash)
  # 重启NFS
  systemctl restart nfs-server
  # 查看结果
  showmount -e localhost
  
  使用PVC
  apps=("kibana")
  size=10Gi
  
  for i in ${apps[@]};do
  cat <<EOF | kubectl -n devops apply -f -
  apiVersion: v1
  kind: PersistentVolumeClaim
  metadata:
    labels:
      app: ${i}
    name: dew-${i}
  spec:
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: ${size}
    selector:
      matchLabels:
        app: ${i}
  ---
  apiVersion: v1
  kind: PersistentVolume
  metadata:
    labels:
      app: ${i}
    name: dew-${i}
  spec:
    capacity:
      storage: ${size}
    accessModes:
      - ReadWriteOnce
    persistentVolumeReclaimPolicy: Recycle
    nfs:
      path: /data/nfs/${apps}
      server: 10.200.131.182
  EOF
  done
  
  helm install --name dew-kibana  stable/kibana  --namespace devops \
      --set image.tag="6.6.1" \
      --set env."ELASTICSEARCH_URL"="http://dew-elasticsearch-client:9200" \
      --set service.internalPort=5601 \
      --set ingress.enabled=true,ingress.hosts={kibana.dew.ms} \
      --set-string ingress.annotations."kubernetes\.io/ingress\.class"=nginx \
      --set-string ingress.annotations."kubernetes\.io/tls-acme"="true" \
      --set ingress.tls[0].hosts={kibana.dew.ms},ingress.tls[0].secretName=kibana-certs \
      --set dashboardImport.enabled=true \
      --set dashboardImport.dashboards."k8s"="https://raw.githubusercontent.com/monotek/kibana-dashboards/master/k8s-fluentd-elasticsearch.json" \
      --set serviceAccount.create=true,serviceAccountName=kibana \
      --set plugins.enabled=true \
      --set persistentVolumeClaim.enabled=true \
      --set persistentVolumeClaim.existingClaim=true \
      --set securityContext.enabled=true \
      --set securityContext.allowPrivilegeEscalation=true \
      --set securityContext.runAsUser=0 \
      --set securityContext.fsGroup=0
  
      # pod调度相关配置，请根据实际情况设值
      --set nodeSelector."tag"="devops" \
      --set tolerations[0].key="key" \
      --set tolerations[0].operator="Equal" \
      --set tolerations[0].value="value" \
      --set tolerations[0].effect="NoSchedule" \
      --set affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key="key" \
      --set affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator=In \
      --set affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values[0]=target-host-name \
  
      # xpack security相关参数：
      --set image.repository=docker.elastic.co/kibana/kibana \
      --set env."XPACK_SECURITY_ENABLED"="true" \
      --set env."ELASTICSEARCH_USERNAME"="kibana" \
      --set env."ELASTICSEARCH_PASSWORD"="dew123456" \
      --set dashboardImport.xpackauth.enabled=true \
      --set dashboardImport.xpackauth.username=kibana\
      --set dashboardImport.xpackauth.password=dew123456
  
  ----
  
  ==== jaeger
  