1. 程式人生 > >Kubernetes應用部署策略實踐

Kubernetes應用部署策略實踐

【摘要】Kubernetes是Google開源的Docker容器叢集管理系統,為容器化的應用提供資源排程、部署執行、服務發現、擴容縮容等整一套功能。在應用部署這塊,類似於其他系統,Kubernetes也提供了一些控制容器部署的方式,本文主要通過實踐的方式介紹一下kubernetes的應用在部署時的部署策略。

幾個概念:

  • Pod:是Kubernetes最基本的部署排程單元,可以包含container,邏輯上表示某種應用的一個例項。比如一個web站點應用由前端、後端及資料庫構建而成,這三個元件將執行在各自的容器中,那麼我們可以建立包含三個container的pod。

  • node: 是 Kubernetes的worker節點,通常也稱作為Minion node。除了執行一些kubernetes的元件以外(kubelet, kube-proxy等),還承擔著執行容器服務的重任。

  • ReplicationController:是pod的複製抽象,用於解決pod的擴容縮容問題。通常,分散式應用為了效能或高可用性的考慮,需要複製多份資源,並且根據負載情況動態伸縮。通過ReplicationController,我們可以指定一個應用需要幾份複製,Kubernetes將為每份複製建立一個pod,並且保證實際執行pod數量總是與該複製數量相等(例如,當前某個pod宕機時,自動建立新的pod來替換)

環境介紹:

為了演示kubernetes應用部署策略,準備了7臺機器(1個kubernetes master節點和6個kubernetes worker節點),如下圖所示。

圖片描述
其中:

1) kubernetes master: hchenk8s1(ubuntu 16.04 LTS)
2) etcd: hchenk8s1(可以和kubernetes master不在一個節點上面)
3) worker nodes: hchenk8s2 - hchenk8s7(總共6臺機器, 作業系統為ubuntu 16.04 LTS)

完了就開始環境搭建,這裡就不演示了,環境搭建部分網上很多。可供參考的比較多。

進入主題

目前,kubernetes提供了3中應用部署策略,下面一一進行介紹:

1. nodeSelector:

nodeSelector是kubernetes提供的最簡單的一種應用部署策略,通過一種key=value的方式來部署使用者的應用。

從這個引數就能看出來,這種策略的排程物件是node,也就是上面說的kubernetes的worker,說的更明白一點是,使用者在建立應用的時候,可以通過nodeSelector來指定某個、或者某組具有某些屬性的worker node來建立這些容器服務。這裡既然提到了需要根據worker node的某些屬性來建立這些容器服務,那就不得不介紹一下worker node的label.

Label: 標籤的意思,使用在worker node上面顧名思義就是用來對worker node進行一些標記的。比如說worker node的cpu架構(ppc64, x86, etc)或者分組資訊啊什麼的。nodeSelector就是通過這些標籤來選擇應用到底要在哪些機器上去部署。

首先先檢視當前kubernetes cluster的worker node的情況。

root@hchenk8s1:~# kubectl get nodes
NAME                 STATUS                                    AGE
9.111.254.207   Ready,SchedulingDisabled   1d
9.111.254.208   Ready                                       1d
9.111.254.209   Ready                                       1d
9.111.254.212   Ready                                       1d
9.111.254.213   Ready                                       1d
9.111.254.214   Ready                                       1d
9.111.254.218   Ready                                       1d

從輸出可以看到目前測試叢集中有6臺worker node和一個不可排程的master節點。

下面我們通過nodeSelector來部署應用,並且應用需要部署在指定的機器上面。

在kubernetes叢集中,kubelet會上報一些機器屬性比如hostname, os, arch等資訊記錄在nodes的label裡面。下面先檢視一下這些label.

[email protected]:~# kubectl get nodes --show-labels
NAME            STATUS                     AGE       LABELS
9.111.254.207   Ready,SchedulingDisabled   1d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=9.111.254.207
9.111.254.208   Ready                      1d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=9.111.254.208
9.111.254.209   Ready                      1d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=9.111.254.209
9.111.254.212   Ready                      1d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=9.111.254.212
9.111.254.213   Ready                      1d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=9.111.254.213
9.111.254.214   Ready                      1d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=9.111.254.214
9.111.254.218   Ready                      1d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=9.111.254.218

從輸出結果可以看到,每個node都有3個label分別是beta.kubernetes.io/arch,beta.kubernetes.io/os,kubernetes.io/hostname。下面通過hostname作為應用部署的選擇策略來部署應用到9.111.254.218機器上面。

以nginx應用為例,準備一個容器應用部署的kubernetes的deployment檔案。

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
        image: nginx_1_8_1
    spec:
      hostNetwork: false
      containers:
      - name: nginx
        image: nginx:1.8.1
        imagePullPolicy: Always
        ports:
        - protocol: TCP
          containerPort: 80
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
      nodeSelector:
        kubernetes.io/hostname: 9.111.254.218

在yaml檔案中加入nodeSelector, 其中key和value分別為label的name和value.

下面就開始見證奇蹟了。

通過kubectl建立應用容器服務。

root@hchenk8s1:~# kubectl  create -f nginx.yaml
deployment "nginx" created
root@hchenk8s1:~# kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     1         1         1            1           9m
root@hchenk8s1:~# kubectl  get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-1245594662-sjjp9   1/1       Running   0          1m        10.1.20.130   9.111.254.218

從輸出可以看到, nginx的容器服務已經部署到了剛剛指定的機器上面。

當然,nodeSelector自身可以支援多個選擇條件,當建立應用的時候,nodeSelector裡面的條件都滿足的機器會被選擇出來用來部署pod.

為了測試nodeSelector多條件支援的測試,我們對6個worker分別進行標記:

root@hchenk8s1:~# kubectl label node 9.111.254.208 storage_type=overlay application_type=web
node "9.111.254.208" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.209 storage_type=overlay application_type=db
node "9.111.254.209" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.212 storage_type=aufs application_type=web
node "9.111.254.212" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.213 storage_type=aufs application_type=db
node "9.111.254.213" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.214 storage_type=devicemapper application_type=web
node "9.111.254.214" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.218 storage_type=devicemapper application_type=db
node "9.111.254.218" labeled

標記後, 叢集結構如下圖所示。
圖片描述

下面通過應用部署來測試nodeSelector的多條件選擇:

場景1:

建立一個nginx web服務,選擇worker node上面,storage_type標記為啊aufs的節點:

期望結果:

nginx web服務部署在節點9.111.254.212上面

步驟:

準備需要建立服務所需要的yaml檔案:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
        image: nginx_1_8_1
    spec:
      hostNetwork: false
      containers:
      - name: nginx
        image: nginx:1.8.1
        imagePullPolicy: IfNotPresent
        ports:
        - protocol: TCP
          containerPort: 80
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
      nodeSelector:
        storage_type: aufs
        application_type: web

從上面的yaml檔案可以看到,nodeSelector裡面定義了兩個條件,分別是storage_type和application_type, 應用只有建立在兩個條件同時滿足的節點上面。

下面開始建立容器服務。

root@hchenk8s1:~# kubectl create -f nginx.yaml
deployment "nginx" created
root@hchenk8s1:~# kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     1         1         1            1           46s
root@hchenk8s1:~# kubectl  get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-2704164239-lr0gj   1/1       Running   0          1m        10.1.58.235   9.111.254.212

從輸出可以看到,nginx服務已經選擇機器9.111.254.212去部署應用。

場景2:

建立一個nginx web服務,選擇worker node上面,storage_type標記為啊btrfs的節點:

期望結果:

nginx web選擇不到合適的機器部署應用。

步驟:

準備需要建立服務所需要的yaml檔案:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
        image: nginx_1_8_1
    spec:
      hostNetwork: false
      containers:
      - name: nginx
        image: nginx:1.8.1
        imagePullPolicy: IfNotPresent
        ports:
        - protocol: TCP
          containerPort: 80
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
      nodeSelector:
        storage_type: btrfs
        application_type: web

下面開始建立容器服務。

[email protected]:~# kubectl create -f nginx.yaml
deployment "nginx" created
[email protected]:~# kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     1         1         1            0           58s
[email protected]:~# kubectl  get pods -o wide
NAME                    READY     STATUS    RESTARTS   AGE       IP        NODE
nginx-155862529-m5pr1   0/1       Pending   0          1m        <none>
[email protected]:~# kubectl describe pods nginx-155862529-m5pr1
Name:       nginx-155862529-m5pr1
Namespace:  default
Node:       /
Labels:     app=nginx
        pod-template-hash=155862529
Status:     Pending
IP:
Controllers:    ReplicaSet/nginx-155862529
Containers:
  nginx:
    Image:  nginx:latest
    Port:   80/TCP
    Limits:
      cpu:  1
      memory:   1Gi
    Requests:
      cpu:  1
      memory:   1Gi
    Volume Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5rj87 (ro)
    Environment Variables:  <none>
Conditions:
  Type      Status
  PodScheduled  False
Volumes:
  default-token-5rj87:
    Type:   Secret (a volume populated by a Secret)
    SecretName: default-token-5rj87
QoS Class:  Guaranteed
Tolerations:    <none>
Events:
  FirstSeen LastSeen    Count   From            SubObjectPath   Type        Reason          Message
  --------- --------    -----   ----            -------------   --------    ------          -------
  1m        27s     8   {default-scheduler }            Warning     FailedScheduling    pod (nginx-155862529-m5pr1) failed to fit in any node
fit failure summary on nodes : MatchNodeSelector (6)

從輸出可以看到,pod建立失敗了,原因是沒有找到合適的機器去部署。

總結一下:nodeSelector通過label選擇機制,提供了比較簡單直觀的pod部署策略,從一些方面實現了節點的親和/反親和的策略。雖然現在仍然存在在kubernetes中,不過相信這個功能會慢慢被接下來要提到的node Affinity和inter-pod affinity取而代之。

2. NodeAffinity

NodeAffinity是kubernetes 1.2的時候整合進來的,概念上類似於上面介紹的nodeSelector, 通過對node label的選擇來部署你的pod的。

先說說nodeAffinity的型別:

目前nodeAffinity支援requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution這兩種型別。從字面意思就能看到,型別一的要求要比型別二的苛刻的多,對於型別一來說,更像是上面介紹的nodeSelector的高階版,而對於型別二來說,在建立pod的時候會根據各種排程條件對可排程的機器進行排序,並且不會像型別一那樣,因為資源不夠或者一些其他原因而建立失敗,退而求其次來去選擇其他的機器繼續建立。

在這兩種型別中,ignoredDuringExecution的意思是在node在執行期間如果label發生了變化,之間通過這些型別部署的pod不會因為node label的變化而去重新部署來滿足已經定義好的親和/反親和的策略。不過社群計劃會針對這些case提供requiredDuringSchedulingRequiredDuringExecution的型別來應對因為node label變化,定義的親和/反親和的策略發生變化的問題,當然,pod可能就需要重新部署來適應已經發生的變化。

下面設計一個場景還試一下:

場景1:

叢集中的6個worker node分別屬於3個不同的組,這裡分別命名為group1, group2, group3. 需要部署一個nignx應用,並且有4個副本,要求nignx應用部署在除了group3以外的其他group上面。

期望結果:

nginx的應用能部署在group1和group2裡的worker node。

步驟:

首先,對叢集中的worker node新增label來標識組資訊。

root@hchenk8s1:~# kubectl label node 9.111.254.208 group=group1
node "9.111.254.208" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.209 group=group1
node "9.111.254.209" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.212 group=group2
node "9.111.254.212" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.213 group=group2
node "9.111.254.213" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.214 group=group3
node "9.111.254.214" labeled
root@hchenk8s1:~# kubectl label node 9.111.254.218 group=group3
node "9.111.254.218" labeled

標識完後的worker node資訊如下圖所示。

圖片描述

下面準備一個用來測試的yaml檔案:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nginx
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        scheduler.alpha.kubernetes.io/affinity: >
          {
            "nodeAffinity": {
              "requiredDuringSchedulingIgnoredDuringExecution": {
                "nodeSelectorTerms": [
                  {
                    "matchExpressions": [
                      {
                        "key": "group",
                        "operator": "In",
                        "values": ["group1", "group2"]
                      }
                    ]
                  }
                ]
              }
            }
          }
    spec:
      hostNetwork: false
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - protocol: TCP
          containerPort: 80
        resources:
          limits:
            cpu: 500m
            memory: 512Mi

下面開始建立容器服務。

root@hchenk8s1:~# kc create -f nginx_nodeaffinity.yaml
deployment "nginx" created
root@hchenk8s1:~# kc get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-3792017226-5cn0s   1/1       Running   0          1m        10.1.36.194   9.111.254.213
nginx-3792017226-ljq9h   1/1       Running   0          1m        10.1.56.66    9.111.254.208
nginx-3792017226-qfbvs   1/1       Running   0          1m        10.1.64.66    9.111.254.212
nginx-3792017226-tdm23   1/1       Running   0          1m        10.1.183.3    9.111.254.209

從測試結果可以看到,4個副本分別部署在了group1和group2上的機器。

上面的例子中用了In的operator,matchExpressions的operator大概有一下幾種:

In: 凡是滿足values裡面條件的機器都會被選擇出來。以上面的例子為例,凡是滿足group=group1或者group=group2的機器都會被選擇出來。

NotIn: 和In相反,凡是滿足values裡面條件的機器都會被剔除出去。如果以上面的例子為例,operator換成NotIn, 那麼group=group1以及group=group2的機器就會被剔除出去,而group=group3的機器則會被選擇出來。

Exists: 和In比較類似,凡是有某個標籤的機器都會被選擇出來。使用Exists的operator的話,values裡面就不能寫東西了。

DoesNotExist: 和Exists相反,凡是不具備某個標籤的機器則會被選擇出來。和Exists的Operator一樣,values裡面也不能寫東西了。

Gt: greater than的意思,表示凡是某個value大於設定的值的機器則會被選擇出來。

Lt: less than的意思,表示凡是某個value小於設定的值的機器則會被選擇出來。

下面2個例子分別看看其他幾個operator的使用以及測試結果。

場景2:

叢集中的6個worker node,其中的2臺標記了network的標籤,而其他的4臺沒有network標籤。通過deployment建立一個nginx應用,並且nginx應用有4個副本,通過nodeAffinity選擇有network標籤的機器進行應用部署。

期望結果:

nginx的應用能部署在有network的標籤的機器上面。

步驟:

首先,對叢集中的worker node新增label來標識組資訊,通過命令可以檢視當前叢集中的worker node的label資訊。

[email protected]:~# kubectl get nodes --show-labels
NAME            STATUS                     AGE       LABELS
9.111.254.208   Ready                      6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group1,kubernetes.io/hostname=9.111.254.208,network=calico
9.111.254.209   Ready                      6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group1,kubernetes.io/hostname=9.111.254.209,network=calico
9.111.254.212   Ready                      6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group2,kubernetes.io/hostname=9.111.254.212
9.111.254.213   Ready                      6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group2,kubernetes.io/hostname=9.111.254.213
9.111.254.214   Ready                      6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group3,kubernetes.io/hostname=9.111.254.214
9.111.254.218   Ready                      6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group3,kubernetes.io/hostname=9.111.254.218

準備建立nginx應用的deployment

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nginx
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        scheduler.alpha.kubernetes.io/affinity: >
          {
            "nodeAffinity": {
              "requiredDuringSchedulingIgnoredDuringExecution": {
                "nodeSelectorTerms": [
                  {
                    "matchExpressions": [
                      {
                        "key": "network",
                        "operator": "Exists"
                      }
                    ]
                  }
                ]
              }
            }
          }
    spec:
      hostNetwork: false
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - protocol: TCP
          containerPort: 80
        resources:
          limits:
            cpu: 500m
            memory: 512Mi

從上面的yaml檔案可以看到,matchExpression裡面定義了nodeAffinity的選擇條件,從上面的例子可以看到,nginx應用期望能建立在有network label的機器上。

下面開始建立應用

root@hchenk8s1:~# kubectl create -f nginx_exist.yaml
deployment "nginx" created
root@hchenk8s1:~# kubectl get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-3031338627-7bbfc   1/1       Running   0          7s        10.1.183.17   9.111.254.209
nginx-3031338627-cd1jz   1/1       Running   0          7s        10.1.56.80    9.111.254.208
nginx-3031338627-wslpb   1/1       Running   0          7s        10.1.183.16   9.111.254.209
nginx-3031338627-zgrxn   1/1       Running   0          7s        10.1.56.79    9.111.254.208

從測試結果可以看到,4個副本分別部署在了有network label的機器上面。

場景3:

叢集中的6個worker node,其中的2臺有kernel-version標籤,用來記錄機器的核心版本。通過deployment建立一個nginx應用,並且nginx應用有4個副本,通過nodeAffinity選擇核心版本範圍來進行應用部署。

期望結果:

期望nginx的應用部署在kerver-version大於0320的機器上面。

步驟:

首先為叢集中的機器新增lable來標示機器的核心版本資訊:

[email protected]:~# kc get nodes --show-labels -l worker=true
NAME            STATUS    AGE       LABELS
9.111.254.208   Ready     6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group1,kernel-version=0310,kubernetes.io/hostname=9.111.254.208,worker=true
9.111.254.209   Ready     6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group1,kernel-version=0404,kubernetes.io/hostname=9.111.254.209,worker=true
9.111.254.212   Ready     6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group2,kubernetes.io/hostname=9.111.254.212,worker=true
9.111.254.213   Ready     6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group2,kubernetes.io/hostname=9.111.254.213,worker=true
9.111.254.214   Ready     6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group3,kubernetes.io/hostname=9.111.254.214,worker=true
9.111.254.218   Ready     6d        beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,group=group3,kubernetes.io/hostname=9.111.254.218,worker=true

從上面的輸出可以看到,9.111.254.208的kernel-version為0310,9.111.254.209的kernel-version為0404.

下面準備一個nginx的yaml檔案,用來建立nginx服務:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nginx
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        scheduler.alpha.kubernetes.io/affinity: >
          {
            "nodeAffinity": {
              "requiredDuringSchedulingIgnoredDuringExecution": {
                "nodeSelectorTerms": [
                  {
                    "matchExpressions": [
                      {
                        "key": "kernel-version",
                        "operator": "Gt",
                        "values": ["0320"]
                      }
                    ]
                  }
                ]
              }
            }
          }
    spec:
      hostNetwork: false
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - protocol: TCP
          containerPort: 80
        resources:
          limits:
            cpu: 200m
            memory: 256Mi

上面的檔案表示的策略是期望建立服務到kernel-version大於0320的機器上面。

下面開始建立;

root@hchenk8s1:~# kubectl create -f nginx_gt.yaml
deployment "nginx" created
root@hchenk8s1:~# kubectl get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-4087060041-2x9lw   1/1       Running   0          4s        10.1.183.26   9.111.254.209
nginx-4087060041-4x1dd   1/1       Running   0          4s        10.1.183.23   9.111.254.209
nginx-4087060041-bgt0z   1/1       Running   0          4s        10.1.183.24   9.111.254.209
nginx-4087060041-brgb3   1/1       Running   0          4s        10.1.183.25   9.111.254.209

從測試結果可以看到,4個副本都建立在了kernel-version為0404的機器上。

3. Inter-pod affinity/anti-affinity

Inter-pod affinity/anti-affinity是kubernetes 1.4開始支援的,pod的部署策略不再單單的只是通過node label的選擇,而是可以從pod層面通過pod的 label來部署自己的應用,簡單點說就是你可以通過inter-pod affinity/anti-affinity來決定自己的容器應用親近或者遠離具有某些label的容器應用。

和nodeAffinity一樣,inter-pod affinity/anti-affinity也有requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution兩種型別,分別表示”hard”和”soft”兩種需求。

場景1:

叢集中有個db容器服務(mysql),通過使用inter-pod affinity使得資料庫上層服務(wordpress)能夠和db容器服務在一臺機器上。

步驟:

  1. 首先準備mysql.yaml檔案並且建立容器服務。
apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    name: mysql
spec:
  containers:
    - resources:
        limits :
          cpu: 0.5
      image: mysql:5.6
      name: mysql
      args:
        - "--ignore-db-dir"
        - "lost+found"
      env:
        - name: MYSQL_ROOT_PASSWORD
          # change this
          value: changeit
      ports:
        - containerPort: 3306
          name: mysql

下面開始建立:

root@hchenk8s1:~# kubectl create -f mysql.yaml
pod "mysql" created
root@hchenk8s1:~# kc get pods -owide --show-labels
NAME      READY     STATUS    RESTARTS   AGE       IP            NODE            LABELS
mysql     1/1       Running   0          8m        10.1.226.66   9.111.254.214   name=mysql

mysql建立好了,下面開始準備wordpress的yaml檔案。

apiVersion: v1
kind: Pod
metadata:
  name: wordpress
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: name
            operator: In
            values:
            - mysql
        topologyKey: kubernetes.io/hostname
  containers:
  - image: wordpress:4.7.3-apache
    name: wordpress
    env:
    - name: WORDPRESS_DB_HOST
      value: 10.1.226.66
    - name: WORDPRESS_DB_PASSWORD
      value: changeit
    ports:
    - containerPort: 80
      name: wordpress

yaml檔案裡面定義了podAffinity, matchExpressions裡面指定了需要選擇name mysql的pod label來部署wordpress的pod.

下面開始建立:

root@hchenk8s1:~# kubectl create -f wordpress.yaml
pod "wordpress" created
root@hchenk8s1:~# kubectl get pods -owide --show-labels
NAME        READY     STATUS    RESTARTS   AGE       IP            NODE            LABELS
mysql       1/1       Running   0          1d        10.1.226.66   9.111.254.214   name=mysql
wordpress   1/1       Running   0          1d        10.1.226.67   9.111.254.214   <none>

從輸出可以看到,wordpress和mysql的pod部署在了一臺機器上面,實現了kubernetes.io/hostname上的親和策略。

場景2.

叢集中有個db容器服務(mysql),通過使用inter-pod anti-affinity使得資料庫上層服務(wordpress)能夠和db容器服務不在一臺機器上。

延用上面的mysql的pod, 直接從wordpress的應用開始。

首先還是從yaml檔案的準備開始:

apiVersion: v1
kind: Pod
metadata:
  name: wordpress
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: name
            operator: In
            values:
            - mysql
        topologyKey: kubernetes.io/hostname
  containers:
  - image: wordpress:4.7.3-apache
    name: wordpress
    env:
    - name: WORDPRESS_DB_HOST
      value: 10.1.226.66
    - name: WORDPRESS_DB_PASSWORD
      value: changeit
    ports:
    - containerPort: 80
      name: wordpress

下面開始建立:

root@hchenk8s1:~# kubectl create -f wordpress.yaml
pod "wordpress" created
root@hchenk8s1:~# kubectl get pods -owide --show-labels
NAME        READY     STATUS    RESTARTS   AGE       IP            NODE            LABELS
mysql       1/1       Running   0          1d        10.1.226.66   9.111.254.214   name=mysql
wordpress   1/1       Running   0          4m        10.1.36.207   9.111.254.213   <none>

從測試結果可以看到,pod分佈在了不同的機器上面。

另外,kubernetes的taints和tolerations也是用來對pod進行排程的,這個會在下期進行介紹。

作者簡介:陳暉,供職於西安IBM, 主要從事雲端計算方面工作,涉及Openstack, Mesos, kubernetes等開源專案,在資源管理 ,資源排程等方面有比較豐富的經驗 。

全天候聚焦IaaS/PaaS/SaaS最新技術動態,深度挖掘技術大咖第一手實踐,及時推送雲行業重大新聞,一鍵關注,總覽國內外雲端計算大勢!
圖片描述

相關推薦

Kubernetes應用部署策略實踐

【摘要】Kubernetes是Google開源的Docker容器叢集管理系統,為容器化的應用提供資源排程、部署執行、服務發現、擴容縮容等整一套功能。在應用部署這塊,類似於其他系統,Kubernetes也提供了一些控制容器部署的方式,本文主要通過實踐的方式介紹一下

replicatedhq-ship 基於Kustomize 專案的快速kubernetes 應用部署工具

replicatedhq-ship 是對Kustomize 專案的擴充套件,我們可以用它來快速的進行三方應用的管理部署, 可以和helm,kubernetes 清單檔案,knative 整合,我們可以方便的進行更新,配置修改,ship 可以 保證與上游變更的同步,而且不會發生git 的合併衝突 安裝

簡化Kubernetes應用部署工具

【編者的話】微服務和容器化給複雜應用部署與管理帶來了極大的挑戰。Helm是目前Kubernetes服務編排領域的唯一開源子專案,做為Kubernetes應用的一個包管理工具,可理解為Kubernetes的apt-get / yum,由Deis 公司發起,該公司已經被微軟收購。Helm通過軟體

Kubernetes應用部署模型解析(原理篇)

十多年來Google一直在生產環境中使用容器執行業務,負責管理其容器叢集的系統就是Kubernetes的前身Borg。其實現在很多工作在Kubernetes專案上的Google開發者先前就在Borg這個專案上工作。多數Kubernetes的應用部署模型的思想都起源於Bor

使用 Helm 包管理工具簡化 Kubernetes 應用部署

當在 Kubernetes 中已經部署很多應用時,後續需要對每個應用的 yaml 檔案進行維護操作,這個過程會變的很繁瑣,我們可以使用 Helm 來簡化這些工作。Helm 是 Kubernetes 的一個包管理工具,用來簡化 Kubernetes 應用的部署和管理。 部署 Helm 客戶端與服務端 部署客戶端

利用Helm簡化Kubernetes應用部署(1)

目錄 利用Helm簡化Kubernetes應用部署  Helm基礎  安裝Helm  使用Visual Studio 2019為Helm編寫一個簡單的應用        利

利用Helm簡化Kubernetes應用部署(2)

目錄 定義Charts  使用Helm部署Demo  Helm常用操作命令   定義Charts 回到之前的“charts”目錄,我們依次進行解讀並進行簡單的修改。 Chart.yaml 配置示例:

Kubernetes 服務部署最佳實踐(一) ——如何更好地設定 Request 與 Limit

如何為容器配置 Request 與 Limit? 這是一個即常見又棘手的問題,這個根據服務型別,需求與場景的不同而不同,沒有固定的答案,這裡結合生產經驗總結了一些最佳實踐,可以作為參考。 ### 所有容器都應該設定 request request 的值並不是指給容器實際分配的資源大小,它僅僅是給排程器看的

Kubernetes 服務部署最佳實踐(二) ——如何提高服務可用性

## 引言 上一篇文章我們圍繞如何合理利用資源的主題做了一些最佳實踐的分享,這一次我們就如何提高服務可用性的主題來展開探討。 怎樣提高我們部署服務的可用性呢?K8S 設計本身就考慮到了各種故障的可能性,並提供了一些自愈機制以提高系統的容錯性,但有些情況還是可能導致較長時間不可用,拉低服務可用性的指標。本文

阿裏雲宣布推出Serverless Kubernetes服務 30秒即可完成應用部署

安全摘要: 阿裏雲宣布推出Serverless Kubernetes服務,容器服務新增Serverless形態。5月2日,阿裏雲宣布推出Serverless Kubernetes服務,容器服務新增Serverless形態。開發者可在5秒內創建集群、30秒部署應用上線。用戶無需管理集群基礎設施,還可根據應用實際

[譯]Kubernetes 分布式應用部署和人臉識別 app 實例

match RR 爭辯 interact 個人 echo 建立 HR 定義 原文地址:KUBERNETES DISTRIBUTED APPLICATION DEPLOYMENT WITH SAMPLE FACE RECOGNITION APP 原文作者:skarlso

Springboot應用部署實踐

一,前言      SpringBoot應用常規部署方式是將其打成一個可執行jar包,使其能夠通過java -jar xxx.jar命令方式進行啟動,因此需要使用Maven等工具進行打包。 二,Maven打包      Springboot應用

如何更高效的通過 Intellij IDEA 將應用部署到容器服務 Kubernetes

前言 在之前的一篇文章中,我們介紹了 如何將一個本地的 Java 應用程式直接部署到阿里雲 ECS ,有不少讀者反饋,如果目前已經在使用阿里雲容器服務 Kubernetes 了,那該如何配合這個外掛部署應用呢?在本文中,我們來介紹 部署應用程式到阿里雲容器服務 Kubernetes 。 關於容器服務

kubernetes 應用快速入門 部署nginx

下面文章只是個人學習使用整理,不做過解釋。。。 kubectl get cs kubectl get nodes [[email protected] ~]# kubectl get pods -n kube-system [[email pr

Spark 2.3.0+Kubernetes應用程式部署

 Spark2.3.0+Kubernetes應用程式部署Spark可以執行在Kubernetes管理的叢集中,利用Native Kubernetes排程的特點已經被加入Spark。目前Kubernetes排程是實驗性的,在未來的版本中,Spark在配置、容器映像、入口可能會有

Kubernetes(k8s)部署安全最佳實踐_Kubernetes中文社群

編者按:本文作者是來自 Aqua Security 的 Amir Jerbi 和 Michael Cherny,他們以大量的案例和經驗為基礎,總結並描述了 Kubernetes 部署中的最佳安全實踐。 Kubernetes 提供了很多能夠提高應用安全的方法。要進行這些配置,就要掌握 Kuber

視音訊解碼服務商Bitmovin是如何採用Kubernetes進行多級應用部署_Kubernetes中文社群

注:Bitmovin是一家視訊音訊編解碼服務商,這篇文章是由公司平臺架構師Daniel Hoelbling-Inzko分享他們在kubernetes進行應用部署的經驗。由有容雲翻譯。 在不同的公有云上執行大規模視訊音訊編解碼平臺是非常有挑戰的。Bitmoving在過去的平臺運維中積累了很多經驗

微軟開源容器開發工具Draft,加快應用程式在Kubernetes環境部署_Kubernetes中文社群

今年4月微軟併購Kubernetes工具開發商Deis後,微軟在近日也開源了容器應用程式開發工具Draft,加速應用程式在Kubernetes環境的部署流程。 目前帶領微軟Azure容器服務團隊的Kubernetes共同創辦人Brendan Burns表示,雖然Kubernetes在部署、管理

如何在 Intellij IDEA 更高效地將應用部署到容器服務 Kubernetes

前言 在之前的一篇文章中,我們介紹了 如何將一個本地的 Java 應用程式直接部署到阿里雲 ECS ,有不少讀者反饋,如果目前已經在使用阿里雲容器服務 Kubernetes 了,那該如何配合這個外掛部署應用呢?在本文中,我們來介紹 部署應用程式到阿里雲容器服務 Kubernetes

Docker+Jenkins+Gitlab+Django應用部署實踐

一、背景介紹 在網際網路應用快速更新迭代的大背景下,傳統的人工手動或簡單指令碼已經不能適應此變化,此時Devops為我們提供了良好的解決方案,應用好CI/CD可以大大的方便我們的日常工作,自動化快速的持續整合/持續交付為我們帶來了應用開放的更快速度、更好的穩定性和更強的可靠性。 二、拓撲環境 2.1 架