kubernetes 上手指南:概念篇

大家好,我叫謝偉语稠,是一名程序員漆弄。

今天的主題:kubernetes 概念篇睦裳,通過一些示例,學習 kubernetes(k8s) 的一些核心概念撼唾。

這些知識不可避免的受筆者經(jīng)驗的限制廉邑,希望大家辯證的看待

kubernetes 角色是“操作系統(tǒng)”

上一節(jié)介紹了容器相關(guān)的知識,引申出單節(jié)點部署多個容器可以使用 docker-compose倒谷。而針對多節(jié)點的部署方案蛛蒙,docker-compose 無能為力,轉(zhuǎn)而介紹今天的角色:kubernetes渤愁。

kubernetes 底層操作的具體資源是容器(學習者需要優(yōu)先掌握容器的相關(guān)知識)牵祟。容器的本質(zhì)是進程,相當于在操作系統(tǒng)上運行的實例抖格。

具體來講:k8s: 是一個跨主機集群的開源容器調(diào)度平臺诺苹,可以自動化的應用容器的部署、擴展和操作雹拄,提供以容器為中心的基礎(chǔ)架構(gòu)收奔。

先拋開 k8s 涉及的具體的知識,就我們熟知的操作系統(tǒng)滓玖,你覺得會包含哪些知識坪哄?

  • 計算:資源管理
  • 存儲:外部的、內(nèi)部的存儲
  • 網(wǎng)絡(luò):應用之間互聯(lián)
  • 擴展:相當于如何安裝各種各樣的軟件
  • 配置:配置文件
  • 權(quán)限:對用戶操作資源進行權(quán)限認證
  • ...

沒錯势篡,k8s 提供這些能力翩肌。

那么 k8s 如何提供的這些能力?

這得從 k8s 架構(gòu)說起禁悠。

k8s 的架構(gòu)借鑒了 Google 內(nèi)部的大規(guī)模集群管理系統(tǒng) Borg念祭,負責對 Google 內(nèi)部很多核心服務(wù)的調(diào)度和管理。

k8s

整體上來說: k8s 包含兩個部分:Master 節(jié)點绷蹲, Node 節(jié)點棒卷。各節(jié)點完成不同的任務(wù)顾孽。

就 Master 而言包含祝钢,其包含4個部分:

  • APIServer: 內(nèi)部的 web 服務(wù)比规,資源操作的入口
  • Scheduler: 調(diào)度器:負責資源的調(diào)度,比如把部署的應用部署在哪個節(jié)點上
  • Controller manager 負責集群的狀態(tài)拦英,比如故障診斷蜒什、自動擴展等
  • etcd 保存集群的整個信息

這四個服務(wù)在 Master 節(jié)點部署完成之后,自動的創(chuàng)建出來:

>> docker ps -a --format "table {{.Image}}\t{{.Names}}"
2c4adeb21b4f            k8s_etcd_etcd-node1_kube-system_119fa7d9bc8bb1c755b9e8f2086d43e6_0
5811259ed0c9            k8s_kube-apiserver_kube-apiserver-node1_kube-system_f92ad4b0d2a33f76b05b6fcbe43e172a_0
07193a77f264            k8s_kube-controller-manager_kube-controller-manager-node1_kube-system_e3f0b6817c856cdb3e54f471dcbddf77_0
0f036524b7a2            k8s_kube-scheduler_kube-scheduler-node1_kube-system_0b5f93df7ddfe3fad5529c9f7f253717_0
k8s.gcr.io/pause:3.1    k8s_POD_kube-scheduler-node1_kube-system_0b5f93df7ddfe3fad5529c9f7f253717_0
k8s.gcr.io/pause:3.1    k8s_POD_kube-controller-manager-node1_kube-system_e3f0b6817c856cdb3e54f471dcbddf77_0
k8s.gcr.io/pause:3.1    k8s_POD_kube-apiserver-node1_kube-system_f92ad4b0d2a33f76b05b6fcbe43e172a_0
k8s.gcr.io/pause:3.1    k8s_POD_etcd-node1_kube-system_119fa7d9bc8bb1c755b9e8f2086d43e6_0

其中每個服務(wù)起來疤估,看上去都有個奇怪的容器:pause ? 后面介紹

就 Node 節(jié)點而言灾常,主要包含:

  • kubelet : 節(jié)點代理,維護容器的生命周期(整個操作過程中铃拇,我們都不太會顯式的操作 kubelet)
  • kube_proxy: 轉(zhuǎn)發(fā)代理钞瀑,負責服務(wù)的發(fā)現(xiàn)和負載均衡
  • docker: 容器

憑借著 k8s 的開放能力,社區(qū)存在很多的插件慷荔,完善 k8s 這個“操作系統(tǒng)”的能力雕什,比如有聚焦在網(wǎng)絡(luò)層面,有聚焦在存儲層面的显晶。

我們的演示都聚焦在 k8s 的原生服務(wù)的能力基礎(chǔ)之上贷岸,不使用其他插件

集群部署

之前說過: k8s 的部署由于各種各樣的原因,對于初學者來說磷雇,整個的部署比較困難偿警,比如對硬件的要求,對網(wǎng)絡(luò)的要求(拉取基礎(chǔ)鏡像)唯笙。

如果你想嘗試試使用 k8s螟蒸, 可以使用下面這個玩具:

Play With k8s

1. master 節(jié)點

kubeadm init --apiserver-advertise-address $(hostname -i)

執(zhí)行結(jié)束,可以看到如何添加其他節(jié)點的命令

2. 網(wǎng)絡(luò)初始化

kubectl apply -n kube-system -f  "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

3. 獲取配置文件

mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

甚至你可以將配置文件拷貝至本地崩掘,在本地使用 kubectl 操作集群資源

安裝部署依賴這幾個軟件:(不過這個玩具都內(nèi)置了)

  • kubeadm: 一鍵式的安裝部署集群的工具尿庐,社區(qū)推薦
  • kubelet: 維護容器生命周期
  • docker: 操作容器
  • kubectl: 操作集群的命令行工具

后續(xù)主要圍繞:kubectl 工具的使用,操作集群

安裝部署后其中有幾個目錄值得我們關(guān)注下:

// master 節(jié)點
>> ls /etc/kubernetes

admin.conf  controller-manager.conf  kubelet.conf  manifests  pki  scheduler.conf

>> ls manifests
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

>> ls pki
apiserver-etcd-client.crt
apiserver-etcd-client.key
apiserver-kubelet-client.crt
apiserver-kubelet-client.key
apiserver.crt
apiserver.key
ca.crt
ca.key
etcd
front-proxy-ca.crt
front-proxy-ca.key
front-proxy-client.crt
front-proxy-client.key
sa.key
sa.pub

主要是自動生成的配置文件呢堰,包括組件:apiserver, etcd, controllermanager, scheduler 的配置文件抄瑟,和一些密鑰認證信息。

事實上 k8s 安裝組件枉疼,是使用配置文件的形式皮假,一般選擇 yaml 的形式(雖然也支持 json 形式,但 yaml 的表達能力更佳骂维,推薦使用)惹资。

查看節(jié)點信息:

包含兩個節(jié)點,其中一個角色是 master 節(jié)點航闺,另一個是普通 node 節(jié)點褪测。

>> kubectl get nodes
NAME    STATUS   ROLES    AGE   VERSION
node1   Ready    <none>   15m   v1.14.9
node2   Ready    master   16m   v1.14.9

如何部署其他組件

一般是通過執(zhí)行 kubectl 命令:

>> kubectl apply -f 1namespace.yml

作為開發(fā)者猴誊,在集群部署完成之后,想要部署自己的服務(wù)侮措,要點在于編寫配置文件懈叹,那么配置文件一般都是什么形式的?

apiVersion: v1
kind: Namespace
metadata:
  name: k8s-example
  labels:
    app: k8s-example
    name: k8s-example
    project: k8s-example

各字段表示如下:

  • apiVersion: 版本信息分扎,比如上文 v1
  • kind: 表示資源類型澄成,比如上文 Namespace
  • metadata: 元信息,一般來定義資源的名稱等

根據(jù)資源類型的不同畏吓,還給不同的資源定義了特殊字段墨状。

整體的 yaml 文件包含四個部分:

apiVersion: 表示版本
kind: 表示資源
metadata: 表示元信息
spec: 資源規(guī)范字段

那么如何知道部署的 k8s 支持哪些資源和版本?這些東西又是哪里來的菲饼?

// 查看所有支持的資源
>> kubectl api-resources

// 查看所有支持的版本
>> kubectl api-versions

還記得 master 節(jié)點有個 api-server 嗎肾砂?是的,定義的 yaml 最終轉(zhuǎn)換成了相應的對象完成資源的增刪改查宏悦,這就是 api-server 主要的作用镐确,也是 k8s 操作資源的入口。

>> kubectl get namespace
NAME           STATUS   AGE
default        Active   264d
k8s-example    Active   7s
kube-public    Active   264d
kube-system    Active   264d
production     Active   263d

除自身剛剛創(chuàng)建的 namespace 之外肛根,集群搭建過程中自動的生成默認的 namespace辫塌。

namespace 是用來進行隔離的,是一個邏輯概念派哲,真實的集群環(huán)境中臼氨,可以根據(jù)使用場景創(chuàng)建不同的 namespace,用來進行隔離芭届。

當然除命令行之外储矩,也可以通過訪問 API 路由的形式操作資源。

>> kubectl proxy
Starting to serve on 127.0.0.1:8001

>> curl http://127.0.0.1:8001/api/v1/namespaces/k8s-example | jq .

{
  "kind": "Namespace",
  "apiVersion": "v1",
  "metadata": {
    "name": "k8s-example",
    "selfLink": "/api/v1/namespaces/k8s-example",
    "uid": "d7f3d7d3-1907-11ea-9746-fa163ed7ee23",
    "resourceVersion": "57568285",
    "creationTimestamp": "2019-12-07T15:40:06Z",
    "labels": {
      "project": "k8s-example"
    },
    "annotations": {
      "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"labels\":{\"project\":\"k8s-example\"},\"name\":\"k8s-example\"}}\n"
    }
  },
  "spec": {
    "finalizers": [
      "kubernetes"
    ]
  },
  "status": {
    "phase": "Active"
  }
}

這個訪問到的比我們之前定義的更詳細褂乍,k8s 會自動添加一些輔助信息持隧。

簡單的說:集群搭建結(jié)束,開發(fā)者需要編寫對應服務(wù)的 yaml 配置文件逃片,這些配置文件區(qū)分不同的對象有不同的規(guī)范要求屡拨。

具體不同資源的規(guī)范有哪些?讀者一方面可以熟悉 k8s 的相關(guān)概念了解相應的規(guī)范褥实。也可以閱讀源代碼從源頭明確規(guī)范的字段呀狼。

// Use of multiple namespaces is optional.
type Namespace struct {
    metav1.TypeMeta `json:",inline"`
    // Standard object's metadata.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`

    // Spec defines the behavior of the Namespace.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
    // +optional
    Spec NamespaceSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`

    // Status describes the current status of a Namespace.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
    // +optional
    Status NamespaceStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}

其中各資源規(guī)范字段即 Spec

kubernetes源碼: https://github.com/kubernetes/kubernetes

那么如何更新資源?

// 修改 yaml 文件

>> kubectl apply -f 1namespace.yml

那么如何刪除資源损离?

>> kubectl delete -f 1namespace.yml

kubectl 命令行還支持各種參數(shù)進行資源的操作哥艇,但我仍然建議:顯式的定義資源,再進行資源的操作僻澎。好處是:1. yaml 的表達能力貌踏,能知道具體的執(zhí)行內(nèi)容是什么 2. 配置文件可管理

相關(guān)概念

比如想部署個 nginx 服務(wù)十饥。

我們已經(jīng)知道需要編寫 yaml 文件,再使用 kubectl 部署祖乳。

# 2nginxpod.yml

apiVersion: v1
kind: Pod
metadata:
  name: k8s-example-pod
  namespace: k8s-example
  labels:
    app: k8s-example-pod
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80

  • 顯式的約定了 namespace: k8s-example逗堵,即會部署在 k8s-example 隔離環(huán)境下,不影響已有服務(wù)
  • spec 約定了部分容器的相關(guān)操作凡资,比如鏡像砸捏,端口

查看服務(wù)部署情況:

>> kubectl get pods --namespace k8s-example
NAME              READY   STATUS    RESTARTS   AGE
k8s-example-pod   1/1     Running   0          3m

查詢指令中谬运,顯式的指定了 namespace, 否則查詢默認(default)的 namespace

再已有的知識中隙赁,加入 nginx 按照容器的方案部署,我們應該可以在本地訪問到其默認主頁梆暖。

那在 k8s 中如何訪問呢伞访?

答案:搭配 service

# 3service.yml
apiVersion: v1
kind: Service
metadata:
  namespace: k8s-example
  name: k8s-example-nginx-service
  labels:
    app: k8s-example-nginx-service
spec:
  selector:
    app: k8s-example-pod
  ports:
    - port: 80
      targetPort: 80
  type: NodePort

  • 顯式的指定 namespace: k8s-example
  • 指定了選擇器: app: k8s-example-pod
  • 約定了端口映射關(guān)系:80:80
  • 約定了類型:NodePort

回歸頭去看 2nginxpod.yml 配置文件中,定義了元信息:app: k8s-example-pod , 定義了容器端口:80轰驳。

所以 service 的角色是和 POD 進行綁定關(guān)系厚掷,POD 本身不提供對外訪問的能力,需要借助 service 進行綁定级解,再對外服務(wù)冒黑。

>> kubectl get service --namespace k8s-example
NAME                        TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
k8s-example-nginx-service   NodePort   10.247.105.43   <none>        80:32511/TCP   1m

master 或者 node 節(jié)點:訪問:

>> curl  http://10.247.105.43:80

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a >nginx.org</a>.<br/>
Commercial support is available at
<a >nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

這種方式其實是集群分配給 cluserIP, 通過 clusterIP 和對應的端口,可以訪問到服務(wù)勤哗。

那么 NodePort 什么意思抡爹?意思是可以使用 該節(jié)點的 IP 和對應的端口。

演示的這個節(jié)點綁定的對外IP: 119.3.198.221
curl http://119.3.198.221:32511/
也可以訪問到服務(wù)

概念整理:

  • 什么是 pod ?
  • pod 如何使其被外部訪問到芒划?

POD

2nginxpod.yml 文件中可以了解到 POD 資源的定義主要圍繞著 容器進行冬竟。沒錯,POD 表示容器組(包含一個或者多個容器)民逼,一般把相關(guān)的容器定義在一個 POD 內(nèi)泵殴,這樣的組合關(guān)系,使其共同服務(wù)于集群拼苍。

POD 是 k8s 調(diào)度的最基本的單位笑诅。

還記得 docker-compose.yml 是如何編寫的嗎?

version: 版本
services: 具體服務(wù)
volumes: 數(shù)據(jù)卷
networks: 網(wǎng)絡(luò)

一般我都會顯式的定義 volumes, networks 這樣定義的所有的服務(wù)都共享 volume 和 network疮鲫。 POD 就是對標的這種思想吆你。使其組合的形式對外服務(wù),各容器之間共享網(wǎng)絡(luò)棚点,數(shù)據(jù)卷等早处。

還記得之前集群部署有個奇怪的 pause 容器嗎?

這是個永遠暫停的容器瘫析,體積非常小砌梆,它的作用就是將 POD 內(nèi)的容器關(guān)聯(lián)起來默责。

那么如何記住 POD 內(nèi)字段的定義?記住 POD 是容器組咸包,那么關(guān)于容器的字段基本都會出現(xiàn)桃序。

比如:

  • container
  • image
  • volume
  • port
  • ...

service

開發(fā)者編寫的服務(wù),如果需要提供對外訪問能力烂瘫,需要 service 進行綁定媒熊,這種綁定關(guān)系是自動,具體的如何綁定主要根據(jù)的 selector 選擇器坟比,選擇器內(nèi)定義的字段芦鳍,在 某個 POD 內(nèi)出現(xiàn)完全吻合的,那么進行綁定葛账。否則處于監(jiān)聽狀態(tài)柠衅,等待符合的對象。

為什么不直接讓 POD 可以直接訪問籍琳?訪問需要綁定 ip 和 端口吧菲宴?但是 POD 在集群內(nèi)是可以隨時刪除、升級趋急、回滾的喝峦。鑒于此不直接提供訪問能力,轉(zhuǎn)而通過 service 進行綁定呜达。

總結(jié):

  • POD 是容器組谣蠢,開發(fā)者在會制造鏡像的基礎(chǔ)上定義自己 POD 的配置文件
  • Service 和 POD 進行綁定,包括訪問類型和端口映射關(guān)系

控制器

ReplicaSet

集群提供高可用服務(wù)的一個重要手段是部署多個相同的服務(wù)闻丑,應用負載均衡的能力漩怎,使其對外服務(wù)。意思是嗦嗡,一般開發(fā)者都不會單獨的定義一個 POD勋锤,也很少單獨寫資源類型是 POD 的配置文件。轉(zhuǎn)而是另一個概念:ReplicaSet (副本)

很明顯侥祭,副本的意思是多個叁执, ReplicaSet 這種資源對象簡單的說是管理 POD 的,比如指定 2 副本矮冬,那么管理的 POD 谈宛, 會有2個一摸一樣的。

# 4replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  namespace: k8s-example
  labels:
    app: k8s-example-replicaset
    name: k8s-example-replicaset
  name: k8s-example-replicaset
spec:
  selector:
    matchLabels:
      app: k8s-example-nginx-pod
  replicas: 2
  template:
    metadata:
      labels:
        app: k8s-example-nginx-pod
    spec:
      containers:
        - name: k8s-example-nginx-pod
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80

  • 顯式的指定 namespace: k8s-example
  • replicat: 2 表示相應的服務(wù)有兩套
  • selector: 選擇器胎署,將符合條件的 POD 納入麾下
  • template: 沒錯 POD 哪些 spec 字段都成為了模版內(nèi)的內(nèi)容

同樣是 nginx 容器吆录。定義的元信息:app: k8s-example-nginx-pod 和之前的不一樣,意味著之前定義的 service 沒法和現(xiàn)在的服務(wù)進行綁定琼牧。那么怎么辦恢筝?

新增一個 service:

# 3service.yml
apiVersion: v1
kind: Service
metadata:
  namespace: k8s-example
  name: k8s-example-nginx-service
  labels:
    app: k8s-example-nginx-service
spec:
  selector:
    app: k8s-example-pod
  ports:
    - port: 80
      targetPort: 80
  type: NodePort
---
apiVersion: v1
kind: Service
metadata:
  namespace: k8s-example
  name: k8s-example-replicaset-service
  labels:
    app: k8s-example-replicaset-service
spec:
  selector:
    app: k8s-example-nginx-pod
  type: NodePort
  ports:
    - port: 80
      nodePort: 31234
      targetPort: 80

  • 多個配置文件可以寫在同一個文件內(nèi)哀卫,使用 --- 分割開
  • 顯示的指定了 nodeport: 31234

默認的會自動的分配:30000-32767 之間的任意一個端口

查看 replicaset:

>> kubectl get replicaset --namespace k8s-example
NAME                     DESIRED   CURRENT   READY   AGE
k8s-example-replicaset   2         2         2       11m

# 也可以查看 pod 

>> kubectl get pods --namespace k8s-example
NAME                           READY   STATUS    RESTARTS   AGE
k8s-example-pod                1/1     Running   0          1h
k8s-example-replicaset-b72k4   1/1     Running   0          9m
k8s-example-replicaset-jd7g6   1/1     Running   0          12m
  • 預期 2個,當前2個撬槽,服務(wù)中2個此改,使用時長 11min。

  • 副本兩個侄柔,為區(qū)分開來共啃,自動的在名稱后加上了隨機字符。

查看 service:

>> kubectl get service --namespace k8s-example
NAME                             TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
k8s-example-nginx-service        NodePort   10.247.105.43   <none>        80:32511/TCP   1h
k8s-example-replicaset-service   NodePort   10.247.134.39   <none>        80:31234/TCP   14m
>> curl http://119.3.198.221:31234/
>> curl http://49.4.54.222:31234/

可以看到都對外提供服務(wù),有人問 119.3.198.22149.4.54.222 是哪里的 IP, 嚯狂男,忘記說了,我這個集群有三個節(jié)點:1個 master (不部署除默認之外的組件), 2個 node, 上面的兩個 IP 是這兩個節(jié)點對外的 ip挂滓。且均勻的分布在節(jié)點上苦银,每個節(jié)點一個(當然有規(guī)則可以使其只部署在一個節(jié)點上啸胧,甚至都不部署在我這個兩個節(jié)點上,直接失斸B病)纺念。

現(xiàn)在明白 type: NodePort 的意思吧?

沒錯想括,ReplicaSet 的資源對象比 POD 上一級陷谱,集群始終根據(jù)副本的個數(shù)在調(diào)控著,比如瑟蜈,你刪掉一個烟逊,立馬給你啟動一個,比如你新增一個铺根,立馬給你刪除一個等宪躯。

Deployment

Deployment 稱作無狀態(tài)工作負載,適合在生產(chǎn)環(huán)境中使用位迂。其具備 ReplicaSet 的所有能力访雪,且支持事件和狀態(tài)查看、回滾掂林、版本記錄等能力臣缀。

看各種文檔,貌似都在弱化 ReplicaSet 的概念泻帮,轉(zhuǎn)而直接介紹 Deployment

同樣部署 nginx精置,資源類型是 Deployment 的配置文件如何編寫?

# 5deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-example-deployment
  labels:
    app: k8s-example-deployment
    name: k8s-example-deployment
  namespace: k8s-example
spec:
  selector:
    matchLabels:
      app: k8s-example-nginx-deployment-pod
  replicas: 2
  template:
    metadata:
      labels:
        app: k8s-example-nginx-deployment-pod
    spec:
      containers:
        - name: k8s-example-nginx-deployment-pod
          imagePullPolicy: IfNotPresent
          image: nginx
          ports:
            - containerPort: 80


除資源類型不同之外锣杂,幾乎和 ReplicaSet 配置一致脂倦。

查看部署情況:

>> kubectl get deployment --namespace k8s-example
NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
k8s-example-deployment   2         2         2            2           4s

比 ReplicaSet 多了個字段 UP-TO-DATE.

>> kubectl describe deployment k8s-example-deployment --namespace k8s-example

Name:                   k8s-example-deployment
Namespace:              k8s-example
CreationTimestamp:      Sun, 08 Dec 2019 10:06:32 +0800
Labels:                 app=k8s-example-deployment
                        name=k8s-example-deployment
Annotations:            deployment.kubernetes.io/revision: 1
                        kubectl.kubernetes.io/last-applied-configuration:
                          {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"k8s-example-deployment","name":"k8s-example-depl...
Selector:               app=k8s-example-nginx-deployment-pod
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=k8s-example-nginx-deployment-pod
  Containers:
   k8s-example-nginx-deployment-pod:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   k8s-example-deployment-6fb599d4b8 (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  99s   deployment-controller  Scaled up replica set k8s-example-deployment-6fb599d4b8 to 2

這種查看詳情的命令主要用來排除問題饲常,查看的字段是 Events, 如何有問題狼讨,會顯示出來贝淤,比如是拉取鏡像出問題,還是調(diào)度出問題等政供。

deployment 管理的 POD 如何提供對外服務(wù)能力播聪,是的,搭配 service.

# 3service.yml
apiVersion: v1
kind: Service
metadata:
  name: k8s-example-deployment-service
  labels:
    app: k8s-example-deployment-service
  namespace: k8s-example
spec:
  selector:
    app: k8s-example-nginx-deployment-pod
  clusterIP: None
  ports:
    - port: 80
      targetPort: 80

這時我們設(shè)置的 clusterIP: None , 表示服務(wù)以 Headless Service 的形式對外訪問布隔,實例間通過服務(wù)發(fā)現(xiàn)訪問离陶。

查看下 service:

>> kubectl get service --namespace k8s-example

NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
k8s-example-deployment-service   ClusterIP   None             <none>        80/TCP         2m
k8s-example-nginx-service        NodePort    10.247.69.248    <none>        80:31519/TCP   2m
k8s-example-replicaset-service   NodePort    10.247.252.231   <none>        80:31234/TCP   2m

可以看到 k8s-example-deployment-service 沒有顯式的提供內(nèi)部集群IP,那怎么訪問到被管理的 POD?

k8s-example-deployment-service.k8s-example.svc.cluster.local
<service-name>.<namespace>.svc.cluster.local

意思是如果你在 service 中定義了 clusterIP: None, 那么該服務(wù)的訪問的 DNS 地址為:<service-name>.<namespace>.svc.cluster.local衅檀,提供內(nèi)部服務(wù)訪問招刨。

具體服務(wù)是選擇何種形式的訪問,需要讀者根據(jù)自己實際的需求進行設(shè)置哀军。

配置文件:configmap, sercret

編寫程序的過程中沉眶,不可避免的會使用到配置文件,自己的程序中一般有兩種方式:

  • 本地配置文件
  • 環(huán)境變量

同樣為說明用法:以部署 mysql 為例杉适。

  • 定義配置文件
# 6setting.yml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: k8s-example
  name: k8s-example-configmap
  labels:
    app: k8s-example-configmap
    name: k8s-example-configmap
data:
  mysql.Database: "root"
  mysql.User: "k8s-example"

---
apiVersion: v1
kind: Secret
metadata:
  name: k8s-example-secret
  labels:
    app: k8s-example-secret
  namespace: k8s-example
data:
  mysql.Port: "MzMwNg=="
  mysql.Password: "cm9vdA=="


兩種資源:configMap 谎倔、secret 的配置字段幾乎一致,區(qū)別在于:secret 中的值都需要 bas64轉(zhuǎn)
碼猿推。

>> kubectl apply -f 6setting.yml
>> kubectl get configmap --namespace k8s-example
NAME                    DATA   AGE
k8s-example-configmap   2      11m

>> kubectl get secret --namespace k8s-example

NAME                  TYPE                                  DATA   AGE
default-secret        kubernetes.io/dockerconfigjson        1      15h
default-token-64tfz   kubernetes.io/service-account-token   3      15hs
k8s-example-secret    Opaque                                2      11m

當然如何你想看具體的配置文件的詳情片习,都可以使用 kubectl describe 進行查看。

  • 配置 service
# 3service.yml
apiVersion: v1
kind: Service
metadata:
  name: k8s-example-mysql-service
  labels:
    app: k8s-example-mysql-service
    name: k8s-example-mysql-service
  namespace: k8s-example
spec:
  selector:
    app: k8s-example-mysql-pod-with-setting
  type: NodePort
  ports:
    - port: 3306
      targetPort: 3306
      nodePort: 32345

查看部署情況:

>> kubectl get service --namespace k8s-example

NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
k8s-example-deployment-service   ClusterIP   None             <none>        80/TCP           5h
k8s-example-mysql-service        NodePort    10.247.1.4       <none>        3306:32345/TCP   17m
k8s-example-nginx-service        NodePort    10.247.69.248    <none>        80:31519/TCP     5h
k8s-example-replicaset-service   NodePort    10.247.252.231   <none>        80:31234/TCP     5h
  • 配置 無狀態(tài)工作負載

deployment 中如何引用相應的配置蹬叭?

# 7deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-example-deployment-with-setting
  labels:
    app: k8s-example-deployment-with-setting
    name: k8s-example-deployment-with-setting
  namespace: k8s-example
spec:
  selector:
    matchLabels:
      app: k8s-example-mysql-pod-with-setting
  replicas: 2
  template:
    metadata:
      labels:
        app: k8s-example-mysql-pod-with-setting
    spec:
      containers:
        - name: k8s-example-mysql-pod-with-setting
          image: mysql
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3306
          resources:
            limits:
              cpu: "1"
              memory: "1024Mi"
            requests:
              cpu: "0.5"
              memory: "500Mi"
          envFrom:
            - configMapRef:
                name: k8s-example-configmap
            - secretRef:
                name: k8s-example-secret
          env:
            - name: MYSQL_DEPLOYMENT
              value: "k8s-example"
            - name: MYSQL_USER
              value: ${mysql.User}
            - name: MYSQL_DATABASE
              value: ${mysql.Database}
            - name: MYSQL_ROOT_PASSWORD
              value: ${mysql.Password}
            - name: METADATA_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: RESOURCE
              valueFrom:
                resourceFieldRef:
                  resource: limits.cpu

其中:resource 字段藕咏,可以用來表明服務(wù)申請和限制 內(nèi)存和CPU,具體可以用數(shù)字來表示秽五,也可以用百分比表示孽查。這種限制有什么用?其中一個比較厲害的功能是動態(tài)的調(diào)整 POD筝蚕,比如你設(shè)置某種策略卦碾,在服務(wù)請求壓力比較大的時候,多開幾個副本起宽,緩解上游請求壓力洲胖。在系統(tǒng)比較閑的時候,刪除幾個副本坯沪,釋放資源绿映。

>> kubectl apply -f 7deployment.yml
>> kubectl get deployment --namespace k8s-example

NAME                                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
k8s-example-deployment                2         2         2            2           5h
k8s-example-deployment-with-setting   2         2         2            2           13m


>> kubectl get pods --namespace k8s-example

NAME                                                   READY   STATUS    RESTARTS   AGE
k8s-example-deployment-6fb599d4b8-bmrnz                1/1     Running   0          5h
k8s-example-deployment-6fb599d4b8-rcc2w                1/1     Running   0          5h
k8s-example-deployment-with-setting-56c7dd7ccc-9k98p   1/1     Running   0          6m
k8s-example-deployment-with-setting-56c7dd7ccc-htwvz   1/1     Running   0          6m
k8s-example-pod                                        1/1     Running   0          15h
k8s-example-replicaset-b72k4                           1/1     Running   0          15h
k8s-example-replicaset-jd7g6                           1/1     Running   0          15h

進入容器內(nèi)查看環(huán)境變量和登錄 mysql,查看數(shù)據(jù)庫試試:

kubectl 對容器的操作幾乎和 docker 的命令一致,這意味著叉弦,如果你熟悉 docker, 使用 kubectl 操作容器幾乎沒有學習成本

>> kubectl exec -it k8s-example-deployment-with-setting-56c7dd7ccc-htwvz --namespace k8s-example -- bash

>> env | grep METADATA
METADATA_NAME=k8s-example-deployment-with-setting-56c7dd7ccc-htwvz

>> env | grep MYSQL_DEPLOYMENT
MYSQL_DEPLOYMENT=k8s-example

>> mysql -u root -p

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| k8s-example        |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

除這些概念之外丐一,k8s 還包括:

  • StatefulSet 有狀態(tài)工作負載,主要應用于工作負載存在先后淹冰,主從依賴等服務(wù)
  • job 單次運行負載
  • cronjob 定時任務(wù)負載
  • daemonSet 守護進程库车,一個節(jié)點上只存在一個,一般用于網(wǎng)絡(luò)或者日志處理等
  • persistenVolume/persistentVolumeClaim 文件掛載相關(guān)

希望這些簡單的示例能夠讓你感受到 k8s 的基本使用方法樱拴。

一般我部署組件抽象出這么幾個步驟:

  • 定義 namespace : 根據(jù)場景定義不同的 namepace 起到邏輯上隔離的作用
  • 定義 configmap/secret 等配置相關(guān)的資源
  • 定義 service 用于綁定 pod , 提供對外服務(wù)
  • 定義 persistentVolume/persistentVolumeClaim 文件掛載相關(guān)
  • 定義 deployment 用于主要的服務(wù)柠衍,即使副本只有一個,也不采用 POD 的形式
  • 定義 statefulSet 用于有狀態(tài)的負載
  • 定義 job 服務(wù)
  • 定義 cronjob 服務(wù)

事實上晶乔,規(guī)劃整套系統(tǒng)的組件的部署的時候珍坊,我會采用清單的形式,按照上面的步驟進行操作正罢。盡管各資源配置文件的定義先后關(guān)系不影響整體服務(wù)阵漏,但我依然建議讀者總結(jié)出一套自己的“清單”。

<完>

參考文檔:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翻具,一起剝皮案震驚了整個濱河市履怯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌呛占,老刑警劉巖虑乖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異晾虑,居然都是意外死亡,警方通過查閱死者的電腦和手機仅叫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門帜篇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诫咱,你說我怎么就攤上這事笙隙。” “怎么了坎缭?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵竟痰,是天一觀的道長。 經(jīng)常有香客問我掏呼,道長坏快,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任憎夷,我火速辦了婚禮莽鸿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己祥得,他們只是感情好兔沃,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著级及,像睡著了一般乒疏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饮焦,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天缰雇,我揣著相機與錄音,去河邊找鬼追驴。 笑死械哟,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的殿雪。 我是一名探鬼主播暇咆,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼丙曙!你這毒婦竟也來了爸业?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤亏镰,失蹤者是張志新(化名)和其女友劉穎扯旷,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體索抓,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡钧忽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了逼肯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耸黑。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖篮幢,靈堂內(nèi)的尸體忽然破棺而出大刊,到底是詐尸還是另有隱情,我是刑警寧澤三椿,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布缺菌,位于F島的核電站,受9級特大地震影響搜锰,放射性物質(zhì)發(fā)生泄漏伴郁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一纽乱、第九天 我趴在偏房一處隱蔽的房頂上張望蛾绎。 院中可真熱鬧,春花似錦、人聲如沸租冠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顽爹。三九已至纤泵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間镜粤,已是汗流浹背捏题。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肉渴,地道東北人公荧。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像同规,于是被迫代替她去往敵國和親循狰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容