容器化Kubernetes(k8s)

1、Kubernetes概述

1.1、Kubernetes介紹

1.1.1、Kubernetes是什麼及作用

Kubernetes(K8S)是Google在2014年發佈的一個開源項目,用於自動化容器化應用程序的部署、擴展和管理。Kubernetes通常結合docker容器工作,並且整合多個運行着docker容器的主機集羣。 官網地址:https://Kubernetes.io
中文社區 https://www.kubernetes.org.cn/docs
Kubernetes的目標是讓部署容器化的應用簡單並且高效,Kubernetes一個核心特點就是能夠自主的管理容器來保證雲平臺中的容器按照用戶的期望運行。以下是Kubernetes相關特性:

  • 自動包裝
    根據資源需求和其他約束自動放置容器,同時不會犧牲可用性,混合關鍵和最大努力的工作負載,以提高資源利用率並節省更多資源。
  • 橫向縮放
    使用簡單的命令或 UI,或者根據 CPU 的使用情況自動調整應用程序副本數。
  • 自動部署和回滾
    Kubernetes 逐漸部署對應用程序或其配置的更改,同時監視應用程序運行狀況,以確保它不會同時終止所有實例。 如果出現問題,Kubernetes會爲您恢復更改,利用日益增長的部署解決方案的生態系統。
  • 存儲編排
    自動安裝您所選擇的存儲系統,無論是本地存儲,如公有云提供商 GCP 或 AWS, 還是網絡存儲系統 NFS,iSCSI, Gluster, Ceph, Cinder, 或 Flocker。
  • 自我修復
    重新啓動失敗的容器,在節點不可用時,替換和重新編排節點上的容器,終止不對用戶定義的健康檢查做出響應的容器,並且不會在客戶端準備投放之前將其通告給客戶端。
  • 服務發現和負載均衡
    不需要修改您的應用程序來使用不熟悉的服務發現機制,Kubernetes 爲容器提供了自己的 IP 地址和一組容器的單個 DNS 名稱,並可以在它們之間進行負載均衡。
  • 密鑰和配置管理
    部署和更新密鑰和應用程序配置,不會重新編譯您的鏡像,不會在堆棧配置中暴露密鑰(secrets)。
  • 批處理
    除了服務之外,Kubernetes還可以管理您的批處理和 CI 工作負載,如果需要,替換出現故障的容器。

使用Kubernetes能做什麼
Kubernetes是一個全新的基於容器技術的分佈式架構領先方案(源於Brog,是google十幾年經驗的結晶);
Kubernetes是一個開放的開發平臺(無侵入性,現有系統很容器遷移到Kubernetes上);
Kubernetes是一個完備的分佈式系統支撐平臺(完善的集羣管理能力)。
使用Kubernetes可以在物理或虛擬機的Kubernetes集羣上運行容器化應用,Kubernetes能夠提供一個以容器爲中心的基礎架構,滿足在生產環境中運行應用的一些常見需求,如:

  • 多個進程協同工作
  • 存儲系統掛載
  • Distributing secrets
  • 應用健康檢測
  • 應用實例的複製
  • Pod自動伸縮/擴展
  • Naming and discovering
  • 負載均衡
  • 滾動更新
  • 資源監控
  • 日誌訪問
  • 調度應用程序
  • 提供認證和授權

爲什麼使用Kubernetes

使用Kubernetes最直接的感受就是我們可以輕裝上陣的開發複雜的系統了;其次Kubernetes是在全面擁抱微服務架構(微服務的核心就是將一個巨大的單體應用拆分成很多小的互相連接的微服務,一個微服務後面可能是多個實例副本在支撐,副本數量可以隨着系統負荷的變化而動態調整);最後Kubernetes系統架構具備超強的橫向擴展能力。

1.1.2、Kubernetes快速入門

  • 環境準備
    • 關閉CentOS防火牆
      systemctl disable firewalld
      systemctl stop firewalld
    • 安裝etcd和kubernetes軟件(docker也順便安裝上了)
      yum install -y etcd kubernetes
    • 啓動服務
      systemctl start etcd
      systemctl start docker
      查看etcd與docker啓動狀態:
# 查看etcd狀態
systemctl status etcd
# 查看docker狀態
systemctl status docker
如果docker啓動失敗,請參考:
vi /etc/sysconfig/selinux 
把selinux後面的改爲disabled,重啓機器,再重啓docker就可以了

              systemctl start kube-apiserver
              systemctl start kube-controller-manager
              systemctl start kube-scheduler
              systemctl start kubelet
              systemctl start kube-proxy

  • 配置
    • tomcat配置(在/usr/local下新建k8s目錄,然後新建下邊的文件)
      • 新建mytomcat-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
 name: mytomcat
spec:
 replicas: 2
 selector:
  app: mytomcat
 template:
  metadata:
   labels:
    app: mytomcat
  spec:
   containers:
    - name: mytomcat
      image: tomcat:7-jre7
      ports:
      - containerPort: 8080

執行命令:kubectl create -f mytomcat-rc.yaml
(查看:kubectl get pods,如果該命令報錯(No resources found),後邊有解決辦法)
在這裏插入圖片描述
發現有兩個tomcat,是因爲在配置文件裏配置了"2":
在這裏插入圖片描述

  • 新建mytomcat-svc.yaml
apiVersion: v1
kind: Service
metadata:
 name: mytomcat
spec:
 type: NodePort
 ports:
  - port: 8080
    nodePort: 30001
 selector:
  app: mytomcat

執行命令:kubectl create -f mytomcat-svc.yaml
(查看svc:kubectl get svc)

  • 常見問題解決
    • docker pull失敗

      • 解決方案1

        1. yum install rhsm -y
        2. docker pull registry.access.redhat.com/rhel7/pod-infrastructure:latest
          如果以上兩步解決問題了,那麼就不需要在執行下面操作
        3. docker search pod-infrastructure
        4. docker pull docker.io/tianyebj/pod-infrastructure
        5. docker tag tianyebj/pod-infrastructure 192.168.126.143:5000/pod-infrastructure
        6. docker push 192.168.126.143:5000/pod-infrastructure
        7. vi /etc/kubernetes/kubelet
          修改 KUBELET_POD_INFRA_CONTAINER="--
          pod-infra-container-image=192.168.237.132:5000/pod- infrastructure:latest"
        8. 重啓服務
          systemctl restart kube-apiserver systemctl restart kube-controller-manager systemctl restart
          kube-scheduler systemctl restart kubelet systemctl restart kube-proxy
      • 解決方案2

        1. docker pull kubernetes/pause

        2. docker tag docker.io/kubernetes/pause:latest
          192.168.237.132:5000/google_containers/pause-amd64.3.0

        3. docker push 192.168.126.143:5000/google_containers/pause-amd64.3.0

        4. vi /etc/kubernetes/kubelet配置爲
          KUBELET_ARGS="--
          pod_infra_container_image=192.168.237.132:5000/google_containers/pause-amd64.3.0"

        5. 重啓kubelet服務 systemctl restart kubelet

    • 外部網不能訪問
      在搭建好的k8s集羣內創建的容器,只能在其所在的節點上curl可訪問,但是在其他任何主機上無法訪問容器佔用的端口
      解決方案:

      1. vim /etc/sysctl.conf
      2. net.ipv4.ip_forward=1
    • 解決 kubectl get pods時No resources found問題

    1. vim /etc/kubernetes/apiserver
    2. 找到”KUBE_ADMISSION_CONTROL="-
      admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota",去掉ServiceAccount,保存退出。
    3. systemctl restart kube-apiserver
      重啓此服務

執行:kubectl get pods命令, 狀態是Running即可,如果狀態爲ContainerCreating就說明有問題,關機重啓所有服務
在這裏插入圖片描述

  • 瀏覽測試(如果瀏覽不可以的話,關機,重啓上邊涉及到的所有服務即可)
http://192.168.237.132:30001/

在這裏插入圖片描述

1.2、Kubernetes 基本架構與常用術語

Kubernetes集羣包含有節點代理kubelet和Master組件(APIs, scheduler, etc),一切都基於分佈式的存儲系統。下面這張圖是Kubernetes的架構圖
在這裏插入圖片描述
在這張系統架構圖中,我們把服務分爲運行在工作節點上的服務和組成集羣級別控制板的服務。
Kubernetes節點有運行應用容器必備的服務,而這些都是受Master的控制。
每次個節點上當然都要運行Docker。Docker來負責所有具體的映像下載和容器運行。

  • Kubernetes主要由以下幾個核心組件組成:
  • etcd保存了整個集羣的狀態;
  • apiserver提供了資源操作的唯一入口,並提供認證、授權、訪問控制、API註冊和發現等機制;
  • controller manager負責維護集羣的狀態,比如故障檢測、自動擴展、滾動更新等;
  • scheduler負責資源的調度,按照預定的調度策略將Pod調度到相應的機器上;
  • kubelet負責維護容器的生命週期,同時也負責Volume(CVI)和網絡(CNI)的管理;
  • Container runtime負責鏡像管理以及Pod和容器的真正運行(CRI);
  • kube-proxy負責爲Service提供cluster內部的服務發現和負載均衡;

除了核心組件,還有一些推薦的Add-ons:

  • kube-dns負責爲整個集羣提供DNS服務
  • Ingress Controller爲服務提供外網入口
  • Heapster提供資源監控
  • Dashboard提供GUI
  • Federation提供跨可用區的集羣
  • Fluentd-elasticsearch提供集羣日誌採集、存儲與查詢

Kubernetes設計理念和功能其實就是一個類似Linux的分層架構

  • 核心層:Kubernetes最核心的功能,對外提供API構建高層的應用,對內提供插件式應用執行環境
  • 應用層:部署(無狀態應用、有狀態應用、批處理任務、集羣應用等)和路由(服務發現、DNS解析等)
  • 管理層:系統度量(如基礎設施、容器和網絡的度量),自動化(如自動擴展、動態Provision等)以及策略
    管理(RBAC、Quota、PSP、NetworkPolicy等)
  • 接口層:kubectl命令行工具、客戶端SDK以及集羣聯邦
  • 生態系統:在接口層之上的龐大容器集羣管理調度的生態系統,可以劃分爲兩個範疇
    • Kubernetes外部:日誌、監控、配置管理、CI、CD、Workflow、FaaS、OTS應用、ChatOps等
    • Kubernetes內部:CRI、CNI、CVI、鏡像倉庫、Cloud Provider、集羣自身的配置和管理等

1.2.1 Cluster

Cluster是計算、存儲和網絡資源的集合,Kubernetes利用這些資源運行各種基於容器的應用.
Kubernetes Cluster由Master和Node組成,節點上運行着若干Kubernetes服務

1.2.2 Master

Master主要職責是調度,即決定將應用放在哪運行。Master運行Linux系統,可以是物理機或虛擬機。 Master是
Kubernetes Cluster的大腦,運行着的Daemon服務包括kube-apiserver、kube-scheduler、kuber-controllermanager、etcd和Pod網絡

  • API Serer(kube-apiserver)
    API Server 提供HTTP/HTTPS RESTful API,即Kubernetes API.是Kubernetes裏所有資源的CRUD等操作的唯
    一入口,也是集羣控制的入口進程
  • Scheduler(kube-scheduler)
    Scheduler負責資源調度的里程,簡單說,它決定將Pod放在哪個Node上運行
  • Controller Manager(kube-controller-manager)
    所有資源對象的自動化控制中心。Controller Manager負責管理Cluster各種資源,保證資源處於預期的狀態。Controller Manager有多種,如replication controller、endpoints controller、namespacecontroller、serviceaccounts controller等。
    不同的controller管理不同的資源,如replication controller管理Deployment、StatefulSet、DaemonSet的生命週期,namespace controller管理Namespace資源
  • etcd
    etcd負責保存Kubernetes Cluster的配置信息和各種資源的狀態信息。當數據發生變化時,etcd會快速地通知Kubernetes相關組件
  • Pod網絡
    Pod要能夠相互通信,Kubernetes Cluster必須部署Pod網絡,flannel是其中一個可選方案

1.2.2 Node

除了Master,Kubernetes集羣中的其它機器被稱爲Node節點。Node職責是運行容器應用,Node由Master管
理,Node負責監控並彙報容器的狀態,同時根據Master的要求管理容器的生命週期。Node也運行在Linux系統,
可以是物理機或虛擬機。
每個Node節點上都運行着以下一組關鍵進程

  • kubelet
    負責Pod對應的容器的創建、啓動等任務,同時與Master節點密切協作,實現集羣管理的基本功能
  • kube-proxy
    實現Kubernetes Service的通信與負載均衡機制的重要組件
  • Docker Enginer
    Docker引擎,負責本機的容器創建和管理工作

1.2.3 Pod

Pod是Kubernetes的最小單元,也是最重要和最基本的概念。每一個Pod包含一個或多個容器,Pod的容器會作爲一個整體被Master調度到一個Node上運行。Kubenetes爲每個Pod都分配了唯一的IP地址,稱爲PodIP,一個Pod裏的多個容器共享PodIP地址。在Kubernetes裏,一個Pod裏的容器與另外主機上的Pod容器能夠直接通信。

1.2.4 Service

Kubernetes Service定義了外界訪問一組特定Pod的方式,Service有自己的IP和端口,Service爲Pod提供了負載均衡。它也是Kubernetes最核心的資源對象之一,每個Service其實就是我們經常提起的微服務架構中的一個"微服務"。

1.2.5 Replication Controller

Replication Controller(簡稱RC)是Kubernetes系統中的核心概念之一,它其實是定義了一個期望的場景,即聲明
某種Pod的副本數量在任意時刻都符合某個預期值,所以RC的定義包括如下幾個部分

  • Pod期待的副本數(replicas)
  • 用於篩選目標Pod的Label Selector
  • 當Pod的副本數量小於預期數量時,用於創建新Pod的Pod模板(template)
    以下是總結的RC的一些特性與作用
  • 在大多數情況下,我們通過定義一個RC實現Pod的創建過程及副本數量的自動控制
  • RC裏包括完整的Pod定義模板
  • RC通過Label Selector機制實現對Pod副本的自動控制
  • 通過改變RC裏的Pod副本數量,可以實現Pod的擴容或縮容功能
  • 通過改變RC裏Pod模板中鏡像版本,可以實現Pod的滾動升級功能

2.Kubernetes集羣

Kubernetes用於協調高度可用的計算機集羣,這些計算機羣集被連接作爲單個單元工作。Kubernetes 在一個集羣
上以更有效的方式自動分發和調度容器應用程序。Kubernetes集羣由兩種類型的資源組成:

  • Master是集羣的調度節點
  • Nodes是應用程序實際運行的工作節點

接下來爲大家講解一下如何快速部署一套Kubernetes集羣,K8S集羣部署有幾種方式:kubeadm、minikube和二進制包。前兩者屬於自動部署,簡化部署操作,我們這裏強烈推薦初學者使用二進制包部署,因爲自動部署屏蔽了很多細節,使得對各個模塊感知很少,非常不利用學習。

2.1、 環境準備與規劃

新建三臺虛擬機(與前邊講的的沒有任何關係,重頭開始搭建集羣),一臺是master,其他兩臺是node

  • 推薦配置2核2G
    Docker version 17.05.0-ce
    角色 IP 組件
    master 192.168.237.133 etcd、kube-apiserver、kube-controller-manager、 kubescheduler、docker
    node01 192.168.237.134 kube-proxy、kubelet、docker
    node02 192.168.237.135 kube-proxy、kubelet、docker

頁面表格中找到Server Binaries中的kubernetes-server-linux-amd64.tar.gz文件,下載到本地。
該壓縮包中包括了k8s需要運行的全部服務程序文件

2.2 Master安裝

2.2.1 Docker安裝

(1)設置yum源

# 建議首先更新yum
yum  update
# 設置yum源
vi /etc/yum.repos.d/docker.repo
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg

(2)安裝docker

yum install docker-engine

(3)安裝後查看docker版本

docker -v

2.2.2 etcd服務

etcd做爲Kubernetes集羣的主要服務,在安裝Kubernetes各服務前需要首先安裝和啓動。

  • 下載etcd二進制文件
    https://github.com/etcd-io/etcd/releases
    在頁面最下方找到下載鏈接(這裏下載好了:https://pan.baidu.com/s/1bp4yTIgPh3VTJup8ZxkwZA
    在這裏插入圖片描述

  • 上傳到master
    在user/local下新建k8s目錄,將上邊下載下來的壓縮包上傳到這個目錄裏,並解壓;

  • 進入解壓後的目錄,將etcd和etcdctl文件複製到/usr/bin目錄
    在這裏插入圖片描述

# 複製到/usr/bin目錄下
cp etcd etcdctl /usr/bin
  • 配置systemd服務文件 /usr/lib/systemd/system/etcd.service (之前沒有,是需要自己新建的)
vi  /usr/lib/systemd/system/etcd.service

將下邊的內容複製進去;注意,下邊有這樣的一個配置WorkingDirectory=/var/lib/etcd/,其中/var/lib/etcd/這個路徑需要手動去創建,即:mkdir -p /var/lib/etcd/

[Unit]
Description=Etcd Server
After=network.target
[Service]
Type=simple
EnvironmentFile=-/etc/etcd/etcd.conf
WorkingDirectory=/var/lib/etcd/
ExecStart=/usr/bin/etcd
Restart=on-failure
[Install]
WantedBy=multi-user.target
  • 啓動與測試etcd服務
systemctl daemon-reload
systemctl enable etcd.service
mkdir -p /var/lib/etcd/
systemctl start etcd.service
# 查看狀態
systemctl status etcd
etcdctl cluster-health

在這裏插入圖片描述

2.2.3、kube-apiserver服務

將kubernetes-server-linux-amd64.tar.gz文件上傳到 /usr/local/k8s目錄,解壓後,進入/server/bin目錄,將kube-apiserver、kube-controller-manager、kube-scheduler以及管理要使用的kubectl二進制命令文件放到/usr/bin目錄,即完成這幾個服務的安裝
在這裏插入圖片描述

cp kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/bin/

下面是對kube-apiserver服務進行配置
編輯systemd服務文件 vi /usr/lib/systemd/system/kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=etcd.service
Wants=etcd.service
[Service]
EnvironmentFile=/etc/kubernetes/apiserver
ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS
Restart=on-failure
Type=notify
[Install]
WantedBy=multi-user.target

配置文件
創建目錄:mkdir /etc/kubernetes
vi /etc/kubernetes/apiserver

KUBE_API_ARGS="--storage-backend=etcd3 --etcd-servers=http://127.0.0.1:2379 --insecure-bind-address=0.0.0.0 --insecure-port=8080 --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,DefaultStorageClass,ResourceQuota --logtostderr=true --log-dir=/var/log/kubernetes --v=2"

調整格式,複製後,注意行首與行末尾別缺少內容
在這裏插入圖片描述

2.2.4、kube-controller-manager服務

kube-controller-manager服務依賴於kube-apiserver服務:
配置systemd服務文件:vi /usr/lib/systemd/system/kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service
[Service]
EnvironmentFile=-/etc/kubernetes/controller-manager
ExecStart=/usr/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

配置文件 vi /etc/kubernetes/controller-manager(複製完後一定要檢查是不是複製對了,本人複製後發現經常缺少橫槓)

KUBE_CONTROLLER_MANAGER_ARGS="--master=http://192.168.237.133:8080 --logtostderr=true --log-dir=/var/log/kubernetes --v=2"

2.2.5 kube-scheduler服務

kube-scheduler服務也依賴於kube-apiserver服務。
配置systemd服務文件:vi /usr/lib/systemd/system/kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service
[Service]
EnvironmentFile=-/etc/kubernetes/scheduler
ExecStart=/usr/bin/kube-scheduler $KUBE_SCHEDULER_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

配置文件:vi /etc/kubernetes/scheduler

KUBE_SCHEDULER_ARGS="--master=http://192.168.237.133:8080 --logtostderr=true --log-dir=/var/log/kubernetes --v=2"

2.2.6 啓動

完成以上配置後,按順序啓動服務
systemctl daemon-reload
systemctl enable kube-apiserver.service
systemctl start kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl start kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl start kube-scheduler.service
檢查每個服務的健康狀態:
systemctl status kube-apiserver.service
systemctl status kube-controller-manager.service
systemctl status kube-scheduler.service

2.3 Node1安裝

在Node1節點上,以同樣的方式把解壓kubernetes-server-linux-amd64.tar.gz文件,從壓縮包中找到這個路徑:k8s/kubernetes/server/bin,將文件kubelet kube-proxy放到/usr/bin目錄中。
在這裏插入圖片描述

cp kubelet kube-proxy /usr/bin

在Node1節點上需要預先安裝docker,請參考Master上Docker的安裝,並啓動Docker

# 啓動docker
systemctl start docker
# 查看docker狀態
systemctl status docker

2.3.1 kubelet服務

配置systemd服務文件:vi /usr/lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=-/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet $KUBELET_ARGS
Restart=on-failure
KillMode=process
[Install]
WantedBy=multi-user.target

mkdir -p /var/lib/kubelet
配置文件:
mkdir /etc/kubernetes;
vi /etc/kubernetes/kubelet

# ip是本機的ip地址
KUBELET_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig --hostname-override=192.168.237.134 --
logtostderr=false --log-dir=/var/log/kubernetes --v=2 --fail-swap-on=false"

用於kubelet連接Master Apiserver的配置文件
vi /etc/kubernetes/kubeconfig

# ip是master所在的機器ip,不是本機的ip,注意縮進
apiVersion: v1
kind: Config
clusters:
 - cluster:
    server: http://192.168.237.133:8080
   name: local
contexts:
 - context:
    cluster: local
   name: mycontext
current-context: mycontext

2.3.2 kube-proxy服務

kube-proxy服務依賴於network服務,所以一定要保證network服務正常,如果network服務啓動失敗,常見解決方案有以下幾中:

1.和 NetworkManager 服務有衝突,這個好解決,直接關閉 NetworkManger 服務就好了, service
NetworkManager stop,並且禁止開機啓動 chkconfig NetworkManager off 。之後重啓就好了
2.和配置文件的MAC地址不匹配,這個也好解決,使用ip addr(或ifconfig)查看mac地址,
將/etc/sysconfig/network-scripts/ifcfg-xxx中的HWADDR改爲查看到的mac地址
3.設定開機啓動一個名爲NetworkManager-wait-online服務,命令爲:
systemctl enable NetworkManager-wait-online.service
4.查看/etc/sysconfig/network-scripts下,將其餘無關的網卡位置文件全刪掉,避免不必要的影響,即只留一個以
ifcfg開頭的文件

配置systemd服務文件:vi /usr/lib/systemd/system/kube-proxy.service

[Unit]
Description=Kubernetes Kube-proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.service
Requires=network.service
[Service]
EnvironmentFile=/etc/kubernetes/proxy
ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_ARGS
Restart=on-failure
LimitNOFILE=65536
KillMode=process
[Install]
WantedBy=multi-user.target

配置文件:vi /etc/kubernetes/proxy

# 第一個地址是master 的ip,第二個地址是本機ip
KUBE_PROXY_ARGS="--master=http://192.168.237.133:8080 --hostname-override=192.168.237.134 --
logtostderr=true --log-dir=/var/log/kubernetes --v=2"

2.3.3 啓動

systemctl daemon-reload
systemctl enable kubelet
systemctl start kubelet
systemctl status kubelet
systemctl enable kube-proxy
systemctl start kube-proxy
systemctl status kube-proxy

2.4 Node2安裝

請參考Node1安裝,注意修改IP;也可以克隆node1,步驟如下
關閉虛擬機,點擊克隆
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
修改ip地址

vi /etc/sysconfig/network-scripts/ifcfg-ens33

在這裏插入圖片描述
在這裏插入圖片描述
重新生成mac地址
在這裏插入圖片描述
將生產的mac地址複製到這裏
在這裏插入圖片描述
關機重啓即可;

2.5 健康檢查與示例測試

  • 查看集羣狀態
# 在master機器上執行該命令
kubectl get nodes
# 如果系統提示上邊這個命令沒找到,則進入到/usr/local/k8s/kubernetes/server/bin這個目錄,執行:
cp kubelet /usr/bin

在這裏插入圖片描述

  • 查看master集羣組件狀態
kubectl get cs

在這裏插入圖片描述

  • 在master裏,進入到/usr/local/k8s目錄,創建 nginx-rc.yaml文件,內容如下:
apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx
spec:
 replicas: 3
 selector:
  app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
     image: nginx
     ports:
     - containerPort: 80

執行命令:kubectl create -f nginx-rc.yaml

  • 在master裏,進入到/usr/local/k8s目錄,創建nginx-svc.yaml文件,內容如下:
apiVersion: v1
kind: Service
metadata:
 name: nginx
spec:
 type: NodePort
 ports:
  - port: 80
    nodePort: 33333
 selector:
   app: nginx

執行命令:kubectl create -f nginx-svc.yaml

  • 查看pod
kubectl get pods

提示:No resources found
找不到該命令
解決上邊這個問題,第一步需要執行前邊所講過的(vi /etc/kubernetes/apiserver,去掉裏邊的ServiceAccount),第二步需要搭建自己的私有倉庫,在node1與node2上搭建一下私有倉庫(node1與node2都需要執行下邊的步驟):

docker pull registry
docker run -di --name=registry -p 5000:5000 registry
修改這個文件
vi /etc/docker/daemon.json
# daemon.json內容是(ip是當前機器的IP):
{"registry-mirrors":["https://docker.mirrors.ustc.edu.cn"],
"insecure-registries":["192.168.237.134:5000"]
}
重啓docker服務 systemctl restart docker

在這裏插入圖片描述

1、docker pull kubernetes/pause
2、docker tag docker.io/kubernetes/pause:latest 192.168.237.134:5000/google_containers/pause-amd64.3.0
3、docker push 192.168.237.134:5000/google_containers/pause-amd64.3.0
4、vi /etc/kubernetes/kubelet,在引號裏的最前邊加上如下內容(注意:pod前是兩個橫槓)
–pod_infra_container_image=192.168.237.134:5000/google_containers/pause-amd64.3.0
在這裏插入圖片描述
5、重啓kubelet服務 systemctl restart kubelet
(查看狀態:systemctl status kubelet)
執行kubectl get pods就不會報錯了:
在這裏插入圖片描述
再等一會,就會變成Running
在這裏插入圖片描述

  • 查看具體pod詳情
kubectl describe  pods nginx-w2lcb

在這裏插入圖片描述
詳情:
在這裏插入圖片描述
在node機器上查看鏡像
在這裏插入圖片描述
發現已經有了nginx鏡像,主要是因爲在master機器裏定義了nginx-rc.yaml,裏邊定義了nginx鏡像,會自動下載到各個node節點裏;

在這裏插入圖片描述

3、階段總結

3.1、K8S架構和組件

在這裏插入圖片描述

3.1.1 Master

  • Kubernetes API Server

    作爲Kubernetes系統的入口,其封裝了核心對象的增刪改查操作,以RESTful API接口方式提供給外部客戶和內部組件調用。維護的REST對象持久化到Etcd中存儲。

  • Kubernetes Scheduler
    爲新建立的Pod進行節點(node)選擇(即分配機器),負責集羣的資源調度。組件抽離,可以方便替換成其他調度器。

  • Kubernetes Controller

    負責執行各種控制器,目前已經提供了很多控制器來保證Kubernetes的正常運行。

  • Replication Controller

    管理維護Replication Controller,關聯Replication Controller和Pod,保證Replication Controller定義的副本數量與實際運行Pod數量一致。

3.1.2 Node

  • Kubelet

    負責管控容器,Kubelet會從Kubernetes API Server接收Pod的創建請求,啓動和停止容器,監控容器運行狀態並彙報給Kubernetes API Server。

  • Kubernetes Proxy

    負責爲Pod創建代理服務,Kubernetes Proxy會從Kubernetes API Server獲取所有的Service信息,並根據Service的信息創建代理服務,實現Service到Pod的請求路由和轉發,從而實現Kubernetes層級的虛擬轉發網絡。

  • Docker

    Node上需要運行容器服務

3.2.K8S集羣搭建常見問題

  • 解決 kubectl get pods時No resources found問題

    1、vim /etc/kubernetes/apiserver
    2、找到”KUBE_ADMISSION_CONTROL="- admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota",去掉ServiceAccount,保存退出。
    3、systemctl restart kube-apiserver 重啓此服務

  • pull 失敗

    • 解決方案1

      1、yum install rhsm -y

      2、docker pull registry.access.redhat.com/rhel7/pod-infrastructure:latest

      如果以上兩步解決問題了,那麼就不需要在執行下面操作

      3、docker search pod-infrastructure

      4、docker pull docker.io/tianyebj/pod-infrastructure

      5、docker tag tianyebj/pod-infrastructure 192.168.126.143:5000/pod-infrastructure

      6、docker push 192.168.126.143:5000/pod-infrastructure

      7、vi /etc/kubernetes/kubelet

      修改 KUBELET_POD_INFRA_CONTAINER="–pod-infra-container-image=192.168.126.143:5000/pod- infrastructure:latest"

      8、重啓服務

      systemctl restart kube-apiserver
      systemctl restart kube-controller-manager
      systemctl restart kube-scheduler
      systemctl restart kubelet
      systemctl restart kube-proxy

    • 解決方案2

      1、docker pull kubernetes/pause

      2、docker tag docker.io/kubernetes/pause:latest 192.168.126.143:5000/google_containers/pause-amd64.3.0

      3、docker push 192.168.126.143:5000/google_containers/pause-amd64.3.0

      4、vi /etc/kubernetes/kubelet配置爲

      ​ KUBELET_ARGS="–pod_infra_container_image=192.168.126.143:5000/google_containers/pause-amd64.3.0"

      5、重啓kubelet服務 systemctl restart kubelet

    私有倉庫搭建
    docker pull registry
    docker run -di --name=registry -p 5000:5000 registry
    修改daemon.json {"insecure-registries":["192.168.126.148:5000"]}
    重啓docker服務 systemctl restart docker
    

3.3.常用命令

  • 獲取當前命名空間下的容器

    kubectl get pods

  • 獲取所有容器l列表

    kubectl get all

  • 創建 容器

    kubectl create -f kubernate-pvc.yaml

  • 刪除容器

    kubectl delete pods/test-pd 或者 kubectl delete -f rc-nginx.yaml

  • 查看指定pod跑在哪個node上

    kubectl get pod /test-pd -o wide

  • 查看容器日誌

    Kubectl logs nginx-8586cf59-mwwtc

  • 進入容器終端命令

    kubectl exec -it nginx-8586cf59-mwwtc /bin/bash

  • 一個Pod裏含有多個容器 用–container or -c 參數。

    例如:假如這裏有個Pod名爲my-pod,這個Pod有兩個容器,分別名爲main-app 和 helper-app,下面的命令將打開到main-app的shell的容器裏。

    kubectl exec -it my-pod --container main-app – /bin/bash

  • 容器詳情列表

    kubectl describe pod/mysql- m8rbl

  • 查看容器狀態

    kubectl get svc

4、容器化進階Kubernetes核心技術

Pod詳解

Pod是Kubernetes的最重要概念,每一個Pod都有一個特殊的被稱爲”根容器“的Pause容器。Pause容器對應的鏡像屬於Kubernetes平臺的一部分,除了Pause容器,每個Pod還包含一個或多個緊密相關的用戶業務容器;
在這裏插入圖片描述

在這裏插入圖片描述

  • Pod vs 應用
    每個Pod都是應用的一個實例,有專用的IP
  • Pod vs 容器
    一個Pod可以有多個容器,彼此間共享網絡和存儲資源,每個Pod 中有一個Pause容器保存所有的容器狀態,通過管理pause容器,達到管理pod中所有容器的效果
  • Pod vs 節點
    同一個Pod中的容器總會被調度到相同Node節點,不同節點間Pod的通信基於虛擬二層網絡技術實現
  • Pod vs Pod
    普通的Pod和靜態Pod

4.1 Pod的定義

下面是yaml文件定義的Pod的完整內容

apiVersion: v1 //版本
kind: Pod //類型,pod
metadata: //元數據
  name: string //元數據,pod的名字
  namespace: string //元數據,pod的命名空間
  labels: //元數據,標籤列表
    - name: string //元數據,標籤的名字
  annotations: //元數據,自定義註解列表
    - name: string //元數據,自定義註解名字
spec: //pod中容器的詳細定義


  containers: //pod中的容器列表,可以有多個容器
  - name: string //容器的名稱
    image: string //容器中的鏡像
    imagesPullPolicy: [Always|Never|IfNotPresent]//獲取鏡像的策略,默認值爲Always,每次都嘗試重新下載鏡像
    command: [string] //容器的啓動命令列表(不配置的話使用鏡像內部的命令)
    rgs: [string] //啓動參數列表
    workingDir: string //容器的工作目錄
    volumeMounts: //掛載到到容器內部的存儲卷設置
    - name: string
      mountPath: string //存儲卷在容器內部Mount的絕對路徑
      readOnly: boolean //默認值爲讀寫
    ports: //容器需要暴露的端口號列表
    - name: string
      containerPort: int //容器要暴露的端口
      hostPort: int //容器所在主機監聽的端口(容器暴露端口映射到宿主機的端口,設置hostPort時同一臺宿主機將不能再啓動該容器的第2份副本)
      protocol: string //TCP和UDP,默認值爲TCP
    env: //容器運行前要設置的環境列表
    - name: string
      value: string
    resources:
      limits: //資源限制,容器的最大可用資源數量
        cpu: Srting
        memory: string
      requeste: //資源限制,容器啓動的初始可用資源數量
        cpu: string
        memory: string
    livenessProbe: //pod內容器健康檢查的設置
      exec:
        command: [string] //exec方式需要指定的命令或腳本
      httpGet: //通過httpget檢查健康
        path: string
	    port: number
		host: string
		scheme: Srtring
		httpHeaders:
		- name: Stirng
		  value: string
	  tcpSocket: //通過tcpSocket檢查健康
		port: number
	  initialDelaySeconds: 0//首次檢查時間
	  timeoutSeconds: 0 //檢查超時時間
	  periodSeconds: 0 //檢查間隔時間
	  successThreshold: 0
	  failureThreshold: 0
	  securityContext: //安全配置
		privileged: falae
    restartPolicy: [Always|Never|OnFailure]//重啓策略,默認值爲Always
    nodeSelector: object //節點選擇,表示將該Pod調度到包含這些label的Node上,以key:value格式指定
    imagePullSecrets:
    - name: string
	
    hostNetwork: false //是否使用主機網絡模式,棄用Docker網橋,默認否

    volumes: //在該pod上定義共享存儲卷列表
    - name: string
	  emptyDir: {} //是一種與Pod同生命週期的存儲卷,是一個臨時目錄,內容爲空
      hostPath: //Pod所在主機上的目錄,將被用於容器中mount的目錄
        path: string
      secret: //類型爲secret的存儲卷
        secretName: string
        item:
        - key: string
          path: string
      configMap: //類型爲configMap的存儲卷
        name: string
        items:
        - key: string
          path: string

4.2 Pod的基本用法

在kubernetes中對運行容器的要求爲:容器的主程序需要一直在前臺運行,而不是後臺運行。應用需要改造成前臺運行的方式。如果我們創建的Docker鏡像的啓動命令是後臺執行程序,則在kubelet創建包含這個容器的pod之後運行完該命令,即認爲Pod已經結束,將立刻銷燬該Pod。如果爲該Pod定義了RC,則創建、銷燬會陷入一個無限循環的過程中。
Pod可以由1個或多個容器組合而成

  • 由一個容器組成的Pod示例
# 一個容器組成的Pod
apiVersion: v1
kind: Pod
metadata:
  name: mytomcat
  labels:
    name: mytomcat
spec:
  containers:
  - name: mytomcat
    image: tomcat
    ports:
    - containerPort: 8000
  • 由兩個爲緊耦合的容器組成的Pod示例
#兩個緊密耦合的容器
apiVersion: v1
kind: Pod
metadata:
  name: myweb
  labels:
    name: tomcat-redis
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
  - name: redis
    image: redis
    ports:
    - containerPort: 6379
  • 創建
kubectl create -f xxx.yaml
  • 查看
kubectl get pod/po <Pod_name>
kubectl get pod/po <Pod_name> -o wide
kubectl describe pod/po <Pod_name>
  • 刪除
kubectl delete -f pod pod_name.yaml
kubectl delete pod --all/[pod_name]

4.3 Pod的分類

Pod有兩種類型

  • 普通Pod
    普通Pod一旦被創建,就會被放入到etcd中存儲,隨後會被Kubernetes Master調度到某個具體的Node上並進行綁定,隨後該Pod對應的Node上的kubelet進程實例化成一組相關的Docker容器並啓動起來。在默認況下,當Pod裏某個容器停止時,Kubernetes會自動檢測到這個問題並且重新啓動這個Pod裏某所有容器,如果Pod所在的Node宕機,則會將這個Node上的所有Pod重新調度到其它節點上。
  • 靜態Pod
    靜態Pod是由kubelet進行管理的僅存在於特定Node上的Pod,它們不能通過 API Server進行管理,無法與ReplicationController、Deployment或DaemonSet進行關聯,並且kubelet也無法對它們進行健康檢查;

4.4 Pod生命週期和重啓策略

  • Pod的狀態
狀態值 說明
Pending API Server已經創建了該Pod,但Pod中的一個或多個容器的鏡像還沒有創建,包括鏡像 下載過程
Running Pod內所有容器已創建,且至少一個容器處於運行狀態、正在啓動狀態或正在重啓狀態
Completed Pod內所有容器均成功執行退出,且不會再重啓
Failed Pod內所有容器均已退出,但至少一個容器退出失敗
Unknown 由於某種原因無法獲取Pod狀態,例如網絡通信不暢
  • Pod重啓策略
    Pod的重啓策略包括Always、OnFailure和Never,默認值是Always
啓策略 說明
Always 當容器失效時,由kubelet自動重啓該容器
OnFailure 當容器終止運行且退出碼不爲0時,由kubelet自動重啓該容器
Never Pod內所有容器均成功執行退出,且不會再重啓
  • 常見狀態轉換
Pod包含的容器數 Pod當前的狀態 發生事件 Pod的結果狀態
RestartPolicy=Always RestartPolicy=OnFailure RestartPolicy=Never
包含一個容器 Running 容器成功退出 Running Succeeded Succeeded
包含一個容器 Running 容器失敗退出 Running Running Failure
包含兩個容器 Running 1個容器失敗退出 Running Running Running
包含兩個容器 Running 容器被OOM殺掉 Running Running Failure

4.5 Pod資源配置

每個Pod都可以對其能使用的服務器上的計算資源設置限額,Kubernetes中可以設置限額的計算資源有CPU與Memory兩種,其中CPU的資源單位爲CPU數量,是一個絕對值而非相對值。Memory配額也是一個絕對值,它的位是內存字節數。
Kubernetes裏,一個計算資源進行配額限定需要設定以下兩個參數:

  • Requests 該資源最小申請數量,系統必須滿足要求
  • Limits 該資源最大允許使用的量,不能突破,當容器試圖使用超過這個量的資源時,可能會被KubernetesKill並重啓
sepc
  containers:
  - name: db
    image: mysql
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

上述代碼表明MySQL容器申請最少0.25個CPU以及64MiB內存,在運行過程中容器所能使用的資源配額爲0.5個CPU以及128MiB內存

5、Label詳解

Label是Kubernetes系統中另一個核心概念。一個Label是一個key=value的鍵值對,其中key與value由用戶自己指定。Label可以附加到各種資源對象上,如Node、Pod、Service、RC,一個資源對象可以定義任意數量的Label,同一個Label也可以被添加到任意數量的資源對象上,Label通常在資源對象定義時確定,也可以在對象創建後動態添加或刪除。
Label的最常見的用法是使用metadata.labels字段,來爲對象添加Label,通過spec.selector來引用對象

apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx
spec:
 replicas: 3
 selector:
  app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
     image: nginx
     ports:
     - containerPort: 80
-------------------------------------
apiVersion: v1
kind: Service
metadata:
 name: nginx
 
spec:
type: NodePort
ports:
 - port: 80
   nodePort: 3333
selector:
app: nginx

Label附加到Kubernetes集羣中的各種資源對象上,目的就是對這些資源對象進行分組管理,而分組管理的核心就是Label Selector。Label與Label Selector都是不能單獨定義,必須附加在一些資源對象的定義文件上,一般附加在RC和Service的資源定義文件中;

6、Replication Controller詳解

Replication Controller(RC)是Kubernetes系統中核心概念之一,當我們定義了一個RC並提交到Kubernetes集羣中以後,Master節點上的Controller Manager組件就得到通知,定期檢查系統中存活的Pod,並確保目標Pod實例的數量剛好等於RC的預期值,如果有過多或過少的Pod運行,系統就會停掉或創建一些Pod.此外我們也可以通過修改RC的副本數量,來實現Pod的動態縮放功能

kubectl scale rc nginx --replicas=5

由於Replication Controller與Kubernetes代碼中的模塊Replication Controller同名,所以在Kubernetes v1.2時,它就升級成了另外一個新的概念Replica Sets,官方解釋爲下一代的RC,它與RC區別是:Replica Sets支援基於集合的Label selector,而RC只支持基於等式的Label Selector。我們很少單獨使用Replica Set,它主要被Deployment這個更高層面的資源對象所使用,從而形成一整套Pod創建、刪除、更新的編排機制。最好不要越過RC直接創建Pod,因爲Replication Controller會通過RC管理Pod副本,實現自動創建、補足、替換、刪除Pod副本,這樣就能提高應用的容災能力,減少由於節點崩潰等意外狀況造成的損失。即使應用程序只有一個Pod副本,也強烈建議使用RC來定義Pod;

7、Replica Set詳解

ReplicaSet 跟 ReplicationController 沒有本質的不同,只是名字不一樣,並且 ReplicaSet 支持集合式的selector(ReplicationController 僅支持等式)。Kubernetes官方強烈建議避免直接使ReplicaSet,而應該通過Deployment來創建RS和Pod。由於ReplicaSet是ReplicationController的代替物,因此用法基本相同,唯一的區別在於ReplicaSet支持集合式的selector;

8、Deployment詳解

Deployment是Kubenetes v1.2引入的新概念,引入的目的是爲了更好的解決Pod的編排問題,Deployment內部使用了Replica Set來實現。Deployment的定義與Replica Set的定義很類似,除了API聲明與Kind類型有所區別:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: frontend
spec:
  replicas: 1
  selector:
  
    matchLabels:
    tier: frontend
  matchExpressions:
    - {key: tier, operator: In, values: [frontend]}
template:
  metadata:
    labels:
      app: app-demo
      tier: frontend
    spec:
      containers:
      - name: tomcat-demo
        image: tomcat
        ports:
        - containerPort: 8080

9、Horizontal Pod Autoscaler

Horizontal Pod Autoscal(Pod橫向擴容 簡稱HPA)與RC、Deployment一樣,也屬於一種Kubernetes資源對象。通過追蹤分析RC控制的所有目標Pod的負載變化情況,來確定是否需要針對性地調整目標Pod的副本數,這是HPA的實現原理。
Kubernetes對Pod擴容與縮容提供了手動和自動兩種模式,手動模式通過kubectl scale命令對一個
Deployment/RC進行Pod副本數量的設置。自動模式則需要用戶根據某個性能指標或者自定義業務指標,並指定Pod副本數量的範圍,系統將自動在這個範圍內根據性能指標的變化進行調整;

  • 手動擴容和縮容
kubectl scale deployment frontend --replicas 1
  • 自動擴容和縮容

HPA控制器基本Master的kube-controller-manager服務啓動參數 --horizontal-pod-autoscaler-sync-period定義的時長(默認值爲30s),週期性地監測Pod的CPU使用率,並在滿足條件時對RC或Deployment中的Pod副本數量進行調整,以符合用戶定義的平均Pod CPU使用率;

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        
        resources:
        requests:
          cpu: 50m
     ports:
     - containerPort: 80
-------------------------------
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
  - port: 80
  selector:
    app: nginx
-----------------------------------
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: app/v1beta1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50

10、Volume詳解

Volume是Pod中能夠被多個容器訪問的共享目錄。Kubernetes的Volume定義在Pod上,它被一個Pod中的多個容器掛載到具體的文件目錄下。Volume與Pod的生命週期相同,但與容器的生命週期不相關,當容器終止或重啓時,Volume中的數據也不會丟失。要使用volume,pod需要指定volume的類型和內容( spec.volumes 字段),和映射到容器的位置( spec.containers.volumeMounts 字段)。 Kubernetes支持多種類型的Volume,包括:
emptyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、nfs、iscsi、flocker、glusterfs、rbd、cephfs、gitRepo、secret、persistentVolumeClaim、downwardAPI、azureFileVolume、azureDisk、vsphereVolume、Quobyte、PortworxVolume、ScaleIO

  • emptyDir
    EmptyDir類型的volume創建於pod被調度到某個宿主機上的時候,而同一個pod內的容器都能讀寫EmptyDir中的同一個文件。一旦這個pod離開了這個宿主機,EmptyDir中的數據就會被永久刪除。所以目前EmptyDir類型的volume主要用作臨時空間,比如Web服務器寫日誌或者tmp文件需要的臨時目錄。yaml示例如下
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: docker.io/nazarpc/webserver
    name: test-container
  volumeMounts:
  - mountPath: /cache
    name: cache-volume
volumes:
- name: cache-volume
  emptyDir: {}
  • hostPath

HostPath屬性的volume使得對應的容器能夠訪問當前宿主機上的指定目錄。例如,需要運行一個訪問
Docker系統目錄的容器,那麼就使用/var/lib/docker目錄作爲一個HostDir類型的volume;或者要在一個容器內部運行CAdvisor,那麼就使用/dev/cgroups目錄作爲一個HostDir類型的volume。一旦這個pod離開了這個宿主機,HostDir中的數據雖然不會被永久刪除,但數據也不會隨pod遷移到其他宿主機上。因此,需要注意的是,由於各個宿主機上的文件系統結構和內容並不一定完全相同,所以相同pod的HostDir可能會在不同的宿主機上表現出不同的行爲。yaml示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: docker.io/nazarpc/webserver
    name: test-container
    # 指定在容器中掛接路徑
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
     # 指定所提供的存儲卷
      volumes:
  - name: test-volume
    # 宿主機上的目錄
    hostPath:
      # directory location on host
      path: /data
  • nfs
    NFS類型的volume。允許一塊現有的網絡硬盤在同一個pod內的容器間共享。yaml示例如下:
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  revisionHistoryLimit: 2
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      # 應用的鏡像
      - image: redis
      name: redis
      imagePullPolicy: IfNotPresent
      # 應用的內部端口
      ports:
      - containerPort: 6379
         name: redis6379
      env:
       - name: ALLOW_EMPTY_PASSWORD
         value: "yes"
       - name: REDIS_PASSWORD
         value: "redis"
       # 持久化掛接位置,在docker中
       volumeMounts:
       - name: redis-persistent-storage
         mountPath: /data
    volumes:
    # 宿主機上的目錄
    - name: redis-persistent-storage
      nfs:
      path: /k8s-nfs/redis/data
      server: 192.168.237.135

11、Namespace詳解

Namespace在很多情況下用於實現多用戶的資源隔離,通過將集羣內部的資源對象分配到不同的Namespace中,形成邏輯上的分組,便於不同的分組在共享使用整個集羣的資源同時還能被分別管理。Kubernetes集羣在啓動後,會創建一個名爲"default"的Namespace,如果不特別指明Namespace,則用戶創建的Pod,RC,Service都將被系統 創建到這個默認的名爲default的Namespace中

  • Namespace創建
apiVersion: v1
kind: Namespace
metadata:
  name: development
---------------------
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: development
spec:
  containers:
  - image: busybox
    command:
     - sleep
     - "3600"
   name: busybox
  • Namespace查看
kubectl get pods --namespace=development

12、Service 詳解

Service是Kubernetes最核心概念,通過創建Service,可以爲一組具有相同功能的容器應用提供一個統一的入口地址,並且將請求負載分發到後端的各個容器應用上

12.1、Service的定義

yaml格式的Service定義文件

apiVersion: v1
kind: Service
matadata:
  name: string
  namespace: string
  labels:
  - name: string
  annotations:
  - name: string
spec:
  selector: []
  type: string
  clusterIP: string
  sessionAffinity: string
  ports:
  - name: string
    protocol: string
    port: int
    targetPort: int
    nodePort: int
  status:
    loadBalancer:
      ingress:
        ip: string
        hostname: string
屬性名稱 取值類型 是否必選 取值說明
version string Required v1
kind string Required Service
metadata object Required 元數據
metadata.name string Required Service名稱
metadata.namespace string Required 命名空間,默認爲default
metadata.labels[] list 自定義標籤屬性列表
metadata.annotation[] string 自定義標籤屬性列表
spec object Required 詳細描述
spec.selector[] list Required Label Selector配置,將選擇具有指定 Label標籤的Pod作爲管理範圍
spec.type string Required Service的類型,指定Service的訪問方 式,默認值爲ClusterIP。取值範圍如 下:ClusterIP: 虛擬服務的IP,用於k8s 集羣內部的pod訪問,在Node上kubeproxy通過設置的Iptables規則進行轉 發。NodePort:使用宿主機的端口,使 用能夠訪問各Node的外部客戶端通過 Node的IP地址和端口就能訪問服務。 LoadBalancer: 使用外接負載均衡器完成 到服務的負載分發,需要在 spec.status.loadBalancer字段指定外部 負載均衡器的IP地址,並同時定義 nodePort和clusterIP,用於公有云環 境
spec.clusterIP string 虛擬服務的IP地址,當type=clusterIP 時,如果不指定,則系統進行自動分 配。也可以手工指定。當 type=LoadBalancer時,則需要指定
spec.sessionAffinity string 是否支持Session,可選值爲ClientIP, 表示將同一個源IP地址的客戶端訪問請求 都轉發到同一個後端Pod。默認值爲空
spec.ports[] list Service需要暴露的端口列表
spec.ports[].name string 端口名稱
spec.ports[].protocol string 端口協議,支持TCP和UDP,默認值爲 TCP
spec.ports[].port int 服務監聽的端口號
spec.ports[].targetPort int 需要轉發到後端Pod的端口號
spec.ports[].nodePort int 當spec.type=NodePort時,指定映射到 物理機的端口號
status object 當spec.type=LoadBalancer時,設置外 部負載均衡器的地址,用於公有云環境
status.loadBalancer object 外部負載均衡器
status.loadBalancer.ingress object 外部負載均衡器
status.loadBalancer.ingress.ip String 外部負載均衡器的IP地址
status.loadBalancer.ingress.hostname string 外部負載均衡器的主機名

12.2、Service的基本用法

一般來說,對外提供服務的應用程序需要通過某種機制來實現,對於容器應用最簡便的方式就是通過TCP/IP機制及監聽IP和端口號來實現。創建一個基本功能的Service

apiVersion: v1
kind: ReplicationController
metadata:
  name: mywebapp
spec:
  replicas: 2
  template:
    metadata:
      name: mywebapp
        labels:
          app: mywebapp
    spec:
      containers:
      - name: mywebapp
      image: tomcat
      ports:
      - containerPort: 8080

我們可以通過kubectl get pods -l app=mywebapp -o yaml | grep podIP來獲取Pod的IP地址和端口號來訪問Tomcat服務,但是直接通過Pod的IP地址和端口訪問應用服務是不可靠的,因爲當Pod所在的Node發生故障時,Pod將被kubernetes重新調度到另一臺Node,Pod的地址會發生改變。我們可以通過配置文件來定義Service,再通過kubectl create來創建,這樣可以通過Service地址來訪問後端的Pod.

apiVersion: v1
kind: Service
metadata:
  name: mywebAppService
spec:
  ports:
  - port: 8081
    targetPort: 8080
  selector:
    app: mywebapp

12.2.1、多端口Service

有時一個容器應用也可能需要提供多個端口的服務,那麼在Service的定義中也可以相應地設置爲將多個端口對應到多個應用服務

apiVersion: v1
kind: Service
metadata:
  name: mywebAppService
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: web
  - port: 8005
    targetPort: 8005
    name: management
  selector:
    app: mywebapp

12.2.2、外部服務Service

在某些特殊環境中,應用系統需要將一個外部數據庫作爲後端服務進行連接,或將另一個集羣或Namespace中的服務作爲服務的後端,這時可以通過創建一個無Label Selector的Service來實現

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
  - protocol: TCP
    port: 80
    	targetPort: 80
--------------------------
apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
- addresses:
  - IP: 10.254.74.3
  ports:
  - port: 8080

k8s部署java項目參考下邊這篇文章
k8s部署java項目

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章