天天看點

初識 K8s,建立一個 guestbook 留言簿應用 Kubernetes 核心概念

原文作者:木環

原文連結:

https://developer.aliyun.com/article/726199

Kubernetes 核心概念

1. 目标概述

本文介紹一個簡單的 K8s 上手應用,希望通過這個簡單的實踐讓大家對 K8s 的核心概念有更深入的了解。

  1. 鞏固 Kubernetes 的基本概念
  2. 學會使用 Kubernetes 部署一個标準的“多層(multi-tier)”應用
  3. 了解 Kubernetes 裡如何通過 Pod,Deployment,Service 等 API 原語描述“應用”

2. 實驗概覽

完成此實驗後,可以掌握的能力有:

本實驗主要在 Kubernetes 叢集上部署一個名叫 guestbook 留言簿的 CURD (增查改删)應用。guestbook 是 Kubernetes 社群的一個經典的應用示例,它有一個 Web 界面來讓使用者進行 CURD 操作,然後向一個 Redis 主節點寫入資料,從多個 Redics 從節點讀去資料。

實驗分以下幾個步驟:

  1. 建立 Redis 主節點
  2. 建立 Redis 從節點叢集
  3. 建立 guestbook 應用
  4. 将 guestbook 應用通過 Service 暴露出來并進行通路
  5. 水準擴充 guestbook 應用

3. 所需資源:

一個完備的 Kubernetes 叢集。您可以選擇阿裡雲容器服務Kubernetes(ACK)進行上手操作。

可以用 Minikube 快速啟動一個單節點叢集(國内建議使用Minikube 中國版),也可以用雲上的 Kubernetes 叢集。本次實驗示範将使用阿裡雲容器服務提供的 Kubernetes 叢集,版本為 1.12。

你可以使用使用 kubectl version 檢視你的叢集版本同實驗版本一緻。

4. 實驗詳情

4.1 建立 Redis 主節點

在這裡,我們使用一個叫做 Deployment 的 API 對象,來描述單執行個體的Redis 主節點。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-master
  labels:
    app: redis
spec:
  selector:
    matchLabels:
      app: redis
      role: master
      tier: backend
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
        role: master
        tier: backend
    spec:
      containers:
      - name: master
        image: registry.cn-hangzhou.aliyuncs.com/kubeapps/redis
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379           

我們需要把這個上述内容儲存為本地 YAML 檔案,名叫:

redis-master-deployment.yaml

。這個檔案主要定義了兩個東西:第一,Pod 裡的容器的鏡像是 redis;第二,這個 Deployment 的執行個體數(replicas)是 1,即指啟動一個 Pod。

然後,我們使用 Kubernetes 的用戶端,執行如下操作:

$  kubectl apply -f  redis-master-deployment.yaml
 deployment.apps/redis-master created           

這一步完成後,Kubernetes 就會按照這個 YAML 檔案裡的描述為你建立對應的 Pod。這種使用方式就是聲明式 API 的典型特征。

接下來,我們可以檢視到這個 Pod:

$ kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
redis-master-68979f4ddd-pg9cv   1/1     Running   0          49s           

可以看到,Pod 已經進入了 Running 狀态,表示一切正常。這時,我們就可以檢視這個 Pod 裡的 Redis 的日志:

$ kubectl logs -f redis-master-68979f4ddd-pg9cv
1:C 26 Apr 2019 18:49:29.303 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 26 Apr 2019 18:49:29.303 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 26 Apr 2019 18:49:29.303 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 26 Apr 2019 18:49:29.304 * Running mode=standalone, port=6379.
1:M 26 Apr 2019 18:49:29.304 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 26 Apr 2019 18:49:29.304 # Server initialized
1:M 26 Apr 2019 18:49:29.304 * Ready to accept connections           

4.2 為 Redis 主節點建立 Service

Kubernetes 裡要通路 Pod 最好通過 Service 的方式,這樣用戶端就不需要記錄 Pod 的 IP 位址了。我們的 guestbook 網站需要通路 Redis 主節點的 Pod,是以也要通過 Service 來做。這個 Service API 對象的定義如下所示:

apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels:
    app: redis
    role: master
    tier: backend
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
    role: master
    tier: backend           

這個 Service 名叫 redis-master,它聲明用自己的 6379 端口代理 Pod 的 6379 端口。

我們還是把上述内容儲存成檔案然後讓 Kubernetes 為我們建立它:

$  kubectl apply -f redis-master-service.yaml
service/redis-master created           

然後我們可以檢視一下這個 Service:

$ kubectl get service
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP    181d
redis-master   ClusterIP   10.107.220.208   <none>        6379/TCP   9s           

這時候,你就可以通過 10.107.220.208:6379 通路到這個 Redis 主節點。

4.3 建立 Redis 從節點叢集

我們這個示例中,有多個 Redis 從節點來共同響應讀請求。同樣的,我們還是通過 Deployment 來描述"一個服務由多個相同的 Pod 執行個體副本組成"這種語義。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-slave
  labels:
    app: redis
spec:
  selector:
    matchLabels:
      app: redis
      role: slave
      tier: backend
  replicas: 2
  template:
    metadata:
      labels:
        app: redis
        role: slave
        tier: backend
    spec:
      containers:
      - name: slave
        image: registry.cn-hangzhou.aliyuncs.com/kubeapps/gb-redisslave:v1
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: env
        ports:
        - containerPort: 6379           

在這個 Deployment 中,我們指定了

replicas: 2

,即這個 Deployment 會啟動兩個相同 Pod(Redis 從節點)。

此外,

gb-redisslave:v1

這個鏡像,會自動讀取

REDIS_MASTER_SERVICE_HOST

這個環境變量的值,也就是 Redis 主節點的 Service 位址,然後用它來組建叢集。這個環境變量是Kubernetes 自動根據 redis-master 這個 Service 名字,自動注入到叢集的每一個 Pod 當中的。

然後,我們建立 Redis 從節點:

$ kubectl apply -f redis-slave-deployment.yaml
deployment.apps/redis-slave created           

這時候,我們就可以檢視這些從節點的狀态:

$ kubectl get pods
NAME                            READY   STATUS              RESTARTS   AGE
redis-master-68979f4ddd-pg9cv   1/1     Running             0          17m
redis-slave-78b464f5cd-2kn7w    0/1     ContainerCreating   0          37s
redis-slave-78b464f5cd-582bk    0/1     ContainerCreating   0          37s           

4.4 為 Redis 從節點建立 Service

類似的,為了讓 guestbook 應用通路上述 Redis 從節點,我們還需要為它們建立一個 Service。在Kubernetes 裡,Service 可以通過 selector 選擇代理多個 Pod,并且負責負載均衡。這個Service 内容如下所示:

apiVersion: v1
kind: Service
metadata:
  name: redis-slave
  labels:
    app: redis
    role: slave
    tier: backend
spec:
  ports:
  - port: 6379
  selector:
    app: redis
    role: slave
    tier: backend           

建立和檢視 Service( 注意:這裡 6379 端口使用了簡化寫法,就不需要寫明 targetPort 了):

$ kubectl apply -f redis-slave-svc.yaml
service/redis-slave created

$ kubectl get services
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP    181d
redis-master   ClusterIP   10.107.220.208   <none>        6379/TCP   16m
redis-slave    ClusterIP   10.101.244.239   <none>        6379/TCP   57s           

這樣,你就可以通過 10.10.101.244:6379 通路到任何一個 Redis 從節點了。

4.5 建立 guestbook 應用

guestbook 應用本身,依然通過一個 Deployment 來描述,如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: guestbook
spec:
  selector:
    matchLabels:
      app: guestbook
      tier: frontend
  replicas: 3
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: registry.cn-hangzhou.aliyuncs.com/kubeapps/gb-frontend:v4
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: env
        ports:
        - containerPort: 80           

這個 YAML 定義了一個 3 副本的 Deployment,即 guestbook 應用會啟動 3 個 Pod。

我們還是通過同樣的步驟建立這個 Deployment:

$ kubectl apply -f frontend.yaml
deployment.apps/frontend created           

檢視 Pod 的狀态:

$ kubectl get pods -l app=guestbook -l tier=frontend
NAME                       READY   STATUS    RESTARTS   AGE
frontend-78d6c59f4-2x24x   1/1     Running   0          3m4s
frontend-78d6c59f4-7mz87   1/1     Running   0          3m4s
frontend-78d6c59f4-sw7f2   1/1     Running   0          3m4s           

4.6 為 guestbook 應用建立 Service

為了能夠讓使用者通路到 guestbook,我們也需要為 guestbook 來建立一個 Service,進而把這個應用以服務的形式暴露出來給使用者使用。

而為了能夠讓 Kubernetes 叢集以外的使用者,這個 Service 就必須是一個外部可通路的 Service。這個在 Kubernetes 裡有幾種做法。在雲上最常見的,是 LoadBalancer 模式。

apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # 自建叢集隻能使用 NodePort 模式
  # type: NodePort 
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: guestbook
    tier: frontend           

由于我的叢集由阿裡雲容器服務提供,是以像上面這樣直接用 LoadBalancer 模式即可。

$ kubectl apply -f frontend-service.yaml           
$ kubectl get service frontend
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
frontend   ClusterIP   172.19.10.209   101.37.192.20     80:32372/TCP   1m           

現在,你隻要用浏覽器打開 EXTERNAL-IP 對應的位址:

http://101.37.192.20:31323

,就可以通路到這個部署好的 guestbook 應用了。

而如果你是自建叢集,那就隻能用 NodePort 模式來實驗(上面 YAML 的注釋已經給出了使用方法)。需要注意的是 NodePort 由于安全性問題,不建議在生産環境中使用。

4.7 水準擴充 guestbook 應用

要通過 Kubernetes 來水準擴充你的應用以響應更多的請求非常簡單,隻需要如下一條指令:

$ kubectl scale deployment frontend --replicas=5
deployment.extensions/frontend scaled           

你就會立刻看到你的 guestbook 應用的執行個體從 3 個變成了 5 個:

$ kubectl get pods -l app=guestbook -l tier=frontend
NAME                       READY   STATUS    RESTARTS   AGE
frontend-78d6c59f4-2x24x   1/1     Running   0          14m
frontend-78d6c59f4-7mz87   1/1     Running   0          14m
frontend-78d6c59f4-chxwd   1/1     Running   0          19s
frontend-78d6c59f4-jrvfx   1/1     Running   0          19s
frontend-78d6c59f4-sw7f2   1/1     Running   0          14m           
“阿裡巴巴雲原生微信公衆号(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術公衆号。”