k8s 簡介

BaichuanWu發表於2019-04-01

1.什麼是Kubernetes

Kubernetes 是一個跨主機叢集的 開源的容器排程平臺,它可以自動化應用容器的部署、擴充套件和操作 , 提供以容器為中心的基礎架構。(官方文件第一行)

1.1 Kubernetes服務於微服務

每個微服務都是獨立的程式,通過定義好的介面(restful api ,amqp)互相呼叫

k8s 簡介

1.1.1 微服務常見的問題

  • 不同服務依賴庫導致的混亂,需要將每個服務獨立開(通過docker改善)
    k8s 簡介
  • 服務註冊,服務發現:需要動態的更新當前服務。
  • 服務編排(即docker容器的編排,docker自身很難解決叢集部署的問題):哪些服務需要在哪些宿主機上啟動

1.2 曾經主流的容器編排工具

  • Docker Swarm
  • Mesos + marathon
  • Kubernetes

2.Kubernetes的主要組成

k8s 簡介

  • master 可以簡單的理解為控制中心
    • etcd:分散式k-v資料庫,根據配置選擇是cp還是ap, k8s只有api server 和etcd通訊, 其他元件均和api server 通訊
    • api server:可以理解為etcd的前置過濾器,換一個視角,它和etcd類似於mysql和檔案系統。
    • controller manager: 核心,負責將現在的狀態調整為etcd上應該的狀態,包含了所有的實現邏輯
    • scheduler: 簡單點說就是給一個pod找一個node。
  • slave 可以簡單的理解為worker
    • kubelet: 負責和master連線,註冊node, listen-watch 本node的任務等
    • kube-proxy: 用於k8s service物件,之後介紹。
    • 容器執行時: 除了docker k8s還支援 rkt等容器實現
  • add-on 一些k8s不提供的功能,需要外掛實現
    • DNS(服務註冊發現)
    • CNI(容器網路介面實現, ex:fannel)

k8s叢集的執行時的大致結構

k8s 簡介

multiple containers run together說的就是pod

3.Kubernetes的常用的幾個物件

1.pods

  • pods是k8s管理的最小物件,是一組共享uts, network, ipc namespace的容器(也支援共享pid,預設不開啟)
  • 每個pod 會有一個 infrastructure 容器,volumne, network其實都是共用的這個容器的network和volumne
  • pod使邏輯上緊密相關的程式適當的隔離,保持一定的相關:
    • 一些程式必須在相同而主機上執行
    • 擴容需要保持一致
    • 等等

k8s 簡介

例項配置檔案

[lukou@khand ~]$ kubectl get po redis-master-jvxld -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubernetes.io/created-by: |
      {"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicationController","namespace":"default","name":"redis-master","uid":"61a3a1c6-43a9-11e9-9f58-00163f007932","apiVersion":"v1","resourceVersion":"510225"}}
  creationTimestamp: 2019-03-11T02:57:17Z
  generateName: redis-master-
  labels:
    name: redis-master
  name: redis-master-jvxld
  namespace: default
  ownerReferences:
  - apiVersion: v1
    controller: true
    kind: ReplicationController
    name: redis-master
    uid: 61a3a1c6-43a9-11e9-9f58-00163f007932
  resourceVersion: "510247"
  selfLink: /api/v1/namespaces/default/pods/redis-master-jvxld
  uid: 61a49472-43a9-11e9-9f58-00163f007932
spec:
  containers:
  - image: kubeguide/redis-master
    imagePullPolicy: Always
    name: master
    ports:
    - containerPort: 6379
      protocol: TCP
    resources: {}
    terminationMessagePath: /dev/termination-log
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-m6g3l
      readOnly: true
    livenessProbe:
      httpGet:
        path: /
        port: 8080
  dnsPolicy: ClusterFirst
  nodeName: 127.0.0.1
  restartPolicy: Always
  securityContext: {}
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  volumes:
  - name: default-token-m6g3l
    secret:
      defaultMode: 420
      secretName: default-token-m6g3l
複製程式碼

2.rc和rs等controller(管理pods)

  • 確保pod健康
  • 確定並動態調整pod 在叢集中中執行的數量,並在pod失敗後重新排程新的pod啟動
  • 類似crontab,進行一些定時任務
    k8s 簡介

除了rc, rs之外,還有deamonSet, job, cronjob等controller

例項配置檔案

apiVersion: v1
kind: ReplicationController
metadata:
  name: kubia
spec:
  replicas: 3
  selector:
    app: kubia
template:
  metadata:
    labels:
      app: kubia
  spec:
    containers:
    - name: kubia
      image: luksa/kubia
      ports:
        - containerPort: 8080
複製程式碼

rc管理pods,但是pods並不是通過rc啟動的, rc將pods的配置檔案同步給api server, Scheduler分配node, Kubelet跑node.

3.service

  • pod是非持久的,會不斷的重啟,導致pod的ip是隨時變化的,同時pod的數量會是動態變化的,客戶端很難和pod直接通訊,service是用來解決這一問題的
  • service 為提供同一服務的pods 提供了統一的入口
  • service 的生命週期內其繫結ip是不會變化的

k8s 簡介

例項配置檔案

apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels: 
    name: redis-master
spec:
  ports:
    - port: 6379
      targetPort: 6379
  selector:
    name: redis-master
複製程式碼
[lukou@khand ~]$ kubectl get svc
NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.254.0.1      <none>        443/TCP    26d
redis-master   10.254.61.141   <none>        6379/TCP   21d
複製程式碼

通過環境變數或者DNS 可以查詢service 的ip和埠

  • 新建的pod會將所有的已經建立service的 ip和port存入環境變數
[lukou@khand ~]$ kubectl get pods
NAME                 READY     STATUS    RESTARTS   AGE
redis-master-jvxld   1/1       Running   0          21d
[lukou@khand ~]$ kubectl exec redis-master-jvxld env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=redis-master-jvxld
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.254.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.254.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.254.0.1
KUBERNETES_SERVICE_HOST=10.254.0.1
KUBERNETES_SERVICE_PORT=443
HOME=/root
[lukou@khand ~]$ kubectl delete po --all
pod "redis-master-jvxld" deleted
[lukou@khand ~]$ kubectl get pods
NAME                 READY     STATUS              RESTARTS   AGE
redis-master-b7mkh   0/1       ContainerCreating   0          6s
[lukou@khand ~]$ ^C
[lukou@khand ~]$ kubectl get pods
NAME                 READY     STATUS    RESTARTS   AGE
redis-master-b7mkh   1/1       Running   0          1m
[lukou@khand ~]$ kubectl exec redis-master-b7mkh env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=redis-master-b7mkh
KUBERNETES_PORT=tcp://10.254.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.254.0.1:443
KUBERNETES_PORT_443_TCP_ADDR=10.254.0.1
REDIS_MASTER_SERVICE_PORT=6379
KUBERNETES_SERVICE_PORT=443
REDIS_MASTER_PORT_6379_TCP_PORT=6379
KUBERNETES_SERVICE_HOST=10.254.0.1
REDIS_MASTER_SERVICE_HOST=10.254.61.141
REDIS_MASTER_PORT=tcp://10.254.61.141:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.254.61.141:6379
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP_PORT=443
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_ADDR=10.254.61.141
HOME=/root
複製程式碼
  • 通過dns服務,註冊cluster域名,類似redis-master.default

之前建立的service只有一個叢集內的固定ip

[lukou@khand ~]$ kubectl get svc
NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.254.0.1      <none>        443/TCP    26d
redis-master   10.254.61.141   <none>        6379/TCP   21d
複製程式碼

如果需要在叢集外訪問有三種方法

  • 預設的service 的型別是 'ClusterIP',修改為NodePort即可
apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels: 
    name: redis-master
spec:
  type: NodePort
  ports:
    - port: 6379
      targetPort: 6379
      nodePort: 30123  // The range of valid ports is 30000-32767
  selector:
    name: redis-master
複製程式碼
[lukou@khand ~]$ kubectl get svc
NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes     10.254.0.1      <none>        443/TCP          26d
redis-master   10.254.61.141   <nodes>       6379:30123/TCP   21d
複製程式碼
  • 建立一個loadbalance
    k8s 簡介
  • 建立Ingress resource
    k8s 簡介

4.deployment

  • 簡單地說deployment是rc的上一層,用來管理rc的
  • 主要功能是管理pod執行的版本
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 3
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        name: nodejs
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
複製程式碼

升級的cmd kubectl set image deployment kubia nodejs=luksa/kubia:v2

大致實現的邏輯是,deployment不斷的降低舊版本rc的 replicas, 增加新版本的replicas

k8s 簡介

就像rc並不是直接控制pod一樣,deployment也是類似,deployment宣告式的通知api server 需要升級後的結果,具體升級的邏輯由development controller去處理

k8s 簡介