DOCKER 學習筆記9 Kubernetes (K8s) 生產級容器編排 上


前言

在上一節的學習中。我們已經可以通過最基本的 Docker Swarm 創建集群,然后在集群里面加入我們需要運行的任務 以及任務的數量 這樣我們就創建了一個服務。 當然,這樣的方式在我們本地虛擬機的情況下,完全適用,並且對於

  • 容器
  • 虛擬主機
  • swarm 創建節點組成集群

有一個很好的理解作用。本節將繼續學習關於 Kubernetes (K8s) 的內容。

Kubernetes 建立在 Google 15年的生產工作負載管理經驗的基礎上,結合了來自社區的最佳理念和實踐。

Kubernetes (K8s)

Kubernetes是Google開源的一個容器編排引擎,它支持自動化部署、大規模可伸縮、應用容器化管理。在生產環境中部署一個應用程序時,通常要部署該應用的多個實例以便對應用請求進行負載均衡。
在Kubernetes中,我們可以創建多個容器,每個容器里面運行一個應用實例,然后通過內置的負載均衡策略,實現對這一組應用實例的管理、發現、訪問,而這些細節都不需要運維人員去進行復雜的手工配置和處理。

節點與管理節點

在K8s 集群包括兩種類型的資源

  • 普通節點 Node 一般用於服務
  • 管理節點 Master 用於管理其他節點

Master 管理節點

Master 負責管理集群。 主服務器協調集群中的所有活動,例如調度應用程序、維護應用程序的期望狀態、縮放應用程序和推出新的更新。

Node 服務節點

Node 是作為 Kubernetes 集群中的工作機器的 VM 或物理計算機。 每個節點都有一個 Kubelet,它是管理節點和與 kubernets 主節點通信的代理。 節點還應該具有處理容器操作的工具,如 Docker

這個還是和在上一節當中學習的Swarm 虛擬機中通過 docker swarm init xx
其實還是有類似的地方的。

image.png

服務執行過程

當您在 Kubernetes 上部署應用程序時,您告訴主控程序啟動應用程序容器。 主服務器安排容器在集群節點上運行。 節點使用主服務器公開的 Kubernetes API 與主服務器通信。 最終用戶還可以直接使用 Kubernetes API 與集群交互。

windows 安裝 kubectl 以及 minikube

若沒有安裝 Docker-toolbox 的同學請參考並安裝:

https://blogs.chaobei.xyz/archives/docker6

下載 kubectl

Kubernetes 命令行工具 kubectl 允許您針對 Kubernetes 集群運行命令。 您可以使用 kubectl 部署應用程序、檢查和管理集群資源以及查看日志。

https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/windows/amd64/kubectl.exe

修改名稱為 kubectl.exe

復制到和docker-toolbox 一樣的目錄下,方便執行

image.png

$ kubectl.exe version  
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2019-12-07T21:20:10Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"windows/amd64"}

下載 minikube

https://github.com/kubernetes/minikube/releases/

選擇合適的版本后,下載,並且修改名稱為 minikube.exe 放到與上面一樣的位置下。

$ minikube.exe version                                                                                                 minikube version: v1.7.2
commit: 50d543b5fcb0e1c0d7c27b1398a9a9790df09dfb

使用 minikube 創建集群

minikube start --image-repository=registry.aliyuncs.com/google_containers --registry-mirror=https://fime0zji.mirror.aliyuncs.com --iso-url=https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.7.0.iso
  • --image-repository 指定使用國內的鏡像倉庫
  • --registry-mirror 將指定的地址傳遞給虛擬機docker 作為拉取鏡像的地址
  • --iso-url 指定minikubo 鏡像的地址。

因為國內防火牆的限制,所以需要將發部分指定為國內地址才可以正常進行。


$ minikube start --image-repository=registry.aliyuncs.com/google_containers --registry-mirror=https://fime0zji.mirror.aliyuncs.com
* Microsoft Windows 10 Pro 10.0.18363 Build 18363 上的 minikube v1.7.2
* Automatically selected the virtualbox driver
* 正在使用鏡像存儲庫 registry.aliyuncs.com/google_containers
* 正在創建 virtualbox 虛擬機(CPUs=2,Memory=2000MB, Disk=20000MB)...
* 找到的網絡選項:
  - NO_PROXY=192.168.99.100,192.168.99.102,192.168.99.103
  - no_proxy=192.168.99.100,192.168.99.102,192.168.99.103
* 正在 Docker 19.03.5 中准備 Kubernetes v1.17.2…
  - env NO_PROXY=192.168.99.100,192.168.99.102,192.168.99.103
  - env NO_PROXY=192.168.99.100,192.168.99.102,192.168.99.103
* 正在啟動 Kubernetes ...
* Enabling addons: default-storageclass, storage-provisioner
* 等待集群上線...
* 完成!kubectl 已經配置至 "minikube"

官網在線測試環境 https://kubernetes.io/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive/

可能遇到的問題

* 正在下載 kubectl v1.17.2
* 正在下載 kubeadm v1.17.2
* 正在下載 kubelet v1.17.2

它可能一直在下載,真的是一直在下,我第一次使用的時候,我足足等了一個小時,現在想起來真的是 MMP 😂

解決方案

  • 找到其所下載的版本
  • 通過FQ的方式下載到本地,放到cache 緩存文件夾下。

kubeadm https://storage.googleapis.com/kubernetes-release/release/v1.17.2/bin/linux/amd64/kubeadm
kubelet https://storage.googleapis.com/kubernetes-release/release/v1.17.2/bin/linux/amd64/kubelet
kubectl.http://mirror.azure.cn/kubernetes/kubectl/v1.17.2/bin/linux/amd64/kubectl

從上面的下載地址里面修改版本號即可下載你想要的版本。

需要FQ上網才能下載,你懂得

image.png

Kubernetes儀表板

minikube dashboard

$ minikube dashboard
* 正在開啟 dashboard ...
* Verifying dashboard health ...
* Launching proxy ...
* Verifying proxy health ...
* Opening http://127.0.0.1:63230/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...

image.png

集群狀態

kubectl cluster-info

因為我們已經安裝了與之交互的 kubectl


$ kubectl.exe cluster-info
Kubernetes master is running at https://192.168.99.113:8443
KubeDNS is running at https://192.168.99.113:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

可以了解到 Kubernets 主節點運行地址以及 Kube 的DNS

獲取所有的節點信息

$ kubectl.exe get nodes                                      

NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   31m   v1.17.2

創建APP 鏡像

image.png

構建一個node 應用

這個應用需要創建在你的minikube 虛擬機內。而不是本地docker

## 創建一個文件夾
mkdir -p nodetest

## 創建自定義鏡像文件並加入以下內容
vi Dockerfile

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

構建測試鏡像

docker build -t mynginx:test .

嘗試運行測試鏡像

$ docker run --name mynginx-d -p 8080:80 mynginx:test

測試訪問

因為我們的的鏡像是跑在虛擬機當中的,獲取其網卡地址后,用8080訪問

使用kubectl創建部署

Kubernetes Pod 是一組由一個或多個容器組成的組,為了管理和聯網的目的而連接在一起。

當我們在 Kubernetes 上創建一個 Deployment 時,Deployment 會創建包含容器的 Pods (而不是直接創建容器)。 每個 Pod 都綁定到節點的預定位置,直到終止(根據重新啟動策略)或刪除為止。 如果節點出現故障,則在集群中的其他可用節點上調度相同的 Pods。

image.png

一個 Pod 總是在一個 Node 上運行。 Node 是 Kubernetes 的工作機器,根據集群的不同,它可以是虛擬機,也可以是物理機器。 每個節點由主節點管理。 一個 Node 可以有多個POD,Kubernetes 主機自動處理跨集群中的 Node 的POD調度。 主機的自動調度考慮到了每個節點上的可用資源。

創建一個POD

Pod 是一組或多個應用程序容器(如 Docker 或 rkt) ,包括共享存儲(卷)、 IP 地址和有關如何運行它們的信息。

kubectl create deployment mynode --image=mynginx:test

使用 kubectl create 命令創建一個管理 Pod 的 Deployment。 Pod 基於所提供的 Docker 圖像運行一個容器。

查看部署

$ kubectl.exe get deployment
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
mynode   1/1     1            1           10s

查看POD

kubectl.exe get pods

$ kubectl.exe get pods                                                                                                  NAME                      READY   STATUS    RESTARTS   AGE
mynode-5479db549c-fm4qk   1/1     Running   0          9m33s

集群事件

kubectl get events

kubectl 配置

kubectl config view

$ kubectl.exe config view                                                                                               apiVersion: v1
clusters:
- cluster:
    certificate-authority: C:\Users\17639\.minikube\ca.crt
    server: https://192.168.99.100:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: C:\Users\17639\.minikube\client.crt
    client-key: C:\Users\17639\.minikube\client.key

創建一個服務暴露你的應用

默認情況下,Pod 只能通過它在 Kubernetes 集群中的內部 IP 地址訪問。 要使 hello-node Container 可以從 Kubernetes 虛擬網絡外部訪問,必須將 Pod 公開為 Kubernetes 服務。

Kubernetes 的服務是一個抽象概念,它定義了一組邏輯 Pods 和一個訪問它們的策略。 服務允許獨立的Pods 之間的松散耦合。 服務是使用 YAML (首選)或 JSON 定義的,就像所有的 Kubernetes 對象一樣。

盡管每個 Pod 都有一個唯一的 IP 地址,但是如果沒有 Service,這些 IP 不會在集群之外公開。 服務允許應用程序接收流量。 通過在 ServiceSpec 中指定類型,可以以不同的方式公開服務:

  • ClusterIP (default) 公開集群中內部 IP 上的服務。 此類型使服務只能從集群內部訪問
  • NodePort 使用 NAT 公開集群中每個選定節點的同一端口上的服務
  • LoadBalancer 負載均衡器,創建一個負載均衡器,並且為服務分配固定IP
  • ExternalName

服務以及標簽

image.png

一組PODS 組成一個服務。服務是一種抽象,它允許POD 在節點關閉時候死亡,以及復制。而不會影響到服務的運行。服務內部依賴的PODS 之間的發現和關聯都是由Kubernets Service 來處理的。

服務使用標簽和選擇器來匹配一組PODS

標簽是附加在對象上的鍵值對,可以以任何方式使用。

image.png

這個圖里面我們可以發現,在管理節點里面部署了兩個應用。每個應用分別將標簽app=B app=A 的所有POD 整理起來組成服務。

創建服務

  • kubectl get pods 查看當前所有的POD
  • kubectl get service 查看當前所有服務

$ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
mynode-5479db549c-lgtfv   1/1     Running   0          56m

$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   16h

kubectl expose deployment mynode --type=NodePort --port=80
將一個deployment 通過服務的方式暴露出去,暴露端口80,也就是我們容器內部的80端口,mynode 是我們已經部署過的一個應用(資源)。

$ kubectl.exe get service mynginx
NAME      TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
mynode    NodePort   10.111.8.25   <none>        80:30857/TCP   5s

這里發現其將我們的服務暴露到了30857下。

此服務的類型:ClusterIP、NodePort、LoadBalancer或ExternalName。默認值為“ClusterIP”。

$ kubectl get deployment                                                                                                                                                                                                                     NAME     READY   UP-TO-DATE   AVAILABLE   AGE
mynode   1/1     1            1           64m

image.png

nodePort

 外部機器可訪問的端口。
比如一個Web應用需要被其他用戶訪問,那么需要配置type=NodePort,而且配置nodePort=30001,那么其他機器就可以通過瀏覽器訪問scheme://node:30001訪問到該服務,例如http://node:30001。
 例如MySQL數據庫可能不需要被外界訪問,只需被內部服務訪問,那么不必設置NodePort

targetPort

 容器的端口(最根本的端口入口),與制作容器時暴露的端口一致(DockerFile中EXPOSE),例如docker.io官方的nginx暴露的是80端口。
 docker.io官方的nginx容器的DockerFile參考https://github.com/nginxinc/docker-nginx

port

 kubernetes中的服務之間訪問的端口,盡管mysql容器暴露了3306端口(參考https://github.com/docker-library/mysql/的DockerFile),但是集群內其他容器需要通過33306端口訪問該服務,外部機器不能訪問mysql服務,因為他沒有配置NodePort類型

參考:https://www.cnblogs.com/devilwind/p/8881201.html

通過標簽的方式查詢

kubectl describe <type> <name> 可以查詢到我們想看的信息,若不填寫名稱,則默認管理節點。

$ kubectl describe deployment
Name:                   mynode
Namespace:              default
CreationTimestamp:      Sun, 16 Feb 2020 12:52:50 +0800
Labels:                 app=mynode
.....

可以看到我們部署的資源的標簽 app=mynode

kubectl get pods -l app=mynode 加入-l 進行標簽查詢。

刪除服務

kubectl delete service <name> 通過名稱刪除一個服務

刪除 POD deployment

先刪除POD 而后刪除 Deployment

## 查看所有POD
kubectl get pods
## 查看所有部署
kubectl get deployment

kubectl delete pod <name>

kubectl delete deployment  <name>

參考

遇到的坑

未使用國內鏡像倉庫


E0215 13:06:36.509035   15568 cache.go:62] save image to file "gcr.io/k8s-minikube/storage-provisioner:v1.8.1" -> "C:\\Users\\17639\\.minikube\\cache\\images\\gcr.io\\k8s-minikube\\storage-provisioner_v1.8.1" failed: nil image for gcr.io/k8s-minikube/storage-provisioner:v1.8.1: Get https://gcr.io/v2/: dial tcp [2404:6800:4008:c03::52]:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM