容器雲方案部署文檔

概述

虛擬機與容器

虛擬機和容器技術的實現了服務器計算環境的抽象和封裝,能夠做爲服務器平臺上的應用程序運行的軟件實體。多臺虛擬機和容器能夠被部署在一臺物理服務器上,或將多臺服務器整合到較少數量的物理服務器上,可是容器技術不是爲了徹底取代傳統虛擬機技術,二者有本質的區別:node

  • 虛擬機技術屬於系統虛擬化,本質上就是在模擬一臺真實的計算機資源,其中包括虛擬CPU,存儲,以及各類虛擬硬件設備——這意味着它也擁有本身的完整訪客操做系統;linux

  • 容器技術則是應用虛擬化,使用沙箱機制虛擬出一個應用程序運行環境,每一個運行的容器實例都能擁有本身獨立的各類命名空間(亦即資源)包括: 進程, 文件系統, 網絡, IPC , 主機名等;nginx

虛擬機將整個操做系統運行在虛擬的硬件平臺上, 進而提供完整的運行環境供應用程序運行,同時也須要消耗更過的宿主機硬件資源; 而Docker等容器化應用時使用的資源都是宿主機系統提供的,僅僅是在資源的使用上只是作了某種程度的隔離與限制.比起虛擬機,容器擁有更高的資源使用效率,實例規模更小、建立和遷移速度也更快.這意味相比於虛擬機,在相同的硬件設備當中,能夠部署數量更多的容器實例,可是計算資源的隔離程度不如虛擬機,因此運行在同一臺宿主機的實例更容易相互影響,甚至主機操做系統崩潰會直接影響運行在宿主機上的全部容器應用。git

在實際生產場景中,須要面臨衆多跨主機的容器協同工做,須要支持各類類型的工做負載,而且要知足可靠性,擴展性,以及面臨隨着業務增加而要解決的性能問題,以及相關的網絡、存儲、集羣,從容器到容器雲的進化隨之出現。docker

構建一個容器雲面臨着衆多的挑戰,首先 Docker引擎的組網能力比較弱,在單一主機網絡能提供較好的支持,但將Docker集羣擴展到多臺主機後,跨主機Docker容器之間的交互和網絡的管理和維護將面臨巨大的挑戰,甚至難覺得繼,所幸不少公司都開發了各自的產品來解決這個問題,典型的如Calico, Flannel, Weave,包括docker1.9版本後提供的Docker Overlay Network支持,其核心思想就是在將不一樣主機上的容器鏈接到同一個虛擬網絡,在這裏咱們選擇了來自CoreOS的Flannel來做爲集羣網路解決方案。後端

在生產環境中,最終面向業務應用須要的容器數量龐大,容器應用間的依賴關係繁雜,若是徹底依賴人工記錄和配置這樣的複雜的關聯信息,而且要知足集羣運行的部署,運行,監控,遷移,高可用等運維需求,實屬力不從心,因此誕生了編排和部署的需求,能解決這類問題的工具備Swarm、Fleet、Kubernetes以及Mesos等,綜合考慮從,最後懸着了來自Google的Kubernetes ---- 一個全徑且全面的容器管理平臺,具備彈性伸縮、垂直擴容、灰度升級、服務發現、服務編排、錯誤恢復及性能監測等功能,能夠輕鬆知足衆多業務應用的運行和維護。centos

容器雲即以容器爲資源分割和調度的基本單位,封裝整個軟件運行時環境,爲開發者和系統管理員提供用於構建、發佈和運行分佈式應用的平臺。最後用一張圖示來歸納整個容器的生態技術棧:api

容器生態技術棧

部署規劃

參考上文圖示,以四臺機器爲例作規劃,一臺主機作master,其餘三臺主機作node節點,全部主機部署centos7, 按照角色爲每臺主機命名:安全

IP 主機名
10.1.10.101 master
10.1.10.102 node1
10.1.10.103 node2
10.1.10.104 node3

每臺主機須要作的配置是:服務器

  • 關閉防火牆,禁用SElinux
  • 配置軟件源, 編輯文件 /etc/yum.repos.d/CentOS-Base.repo,完成以下修改:
[base]
name=CentOS-$releasever - Base - 163.com
baseurl=http://mirrors.163.com/centos/7.4.1708/os/x86_64/
gpgcheck=0
enabled=1

[extras]
name=CentOS-$releasever - Extras - 163.com
baseurl=http://mirrors.163.com/centos/7.4.1708/extras/x86_64/
gpgcheck=0
enabled=1

[k8s-1.8]
name=K8S 1.8
baseurl=http://onwalk.net/repo/
gpgcheck=0
enabled=1
  • 添加四臺主機名的解析,能夠修改/etc/hosts,添加以下配置:
10.1.10.101  master
10.1.10.102  node1
10.1.10.103  node2
10.1.10.104  node3

docker集羣部署與配置

首先要實現跨物理機的容器訪問——是不一樣物理內的容器可以互相訪問,四臺機器,在master主機上部署etcd,三臺機器安裝flannel和docker。

主機 安裝軟件
master etcd
node1 flannel、docker
node2 flannel、docker
node3 flannel、docker

簡單的說flannel作了三件事情:

  1. 數據從源容器中發出後,經由所在主機的docker0虛擬網卡轉發到flannel0虛擬網卡,這是個P2P的虛擬網卡,flanneld服務監聽在網卡的另一端。Flannel也是經過修改Node的路由表實現這個效果的。
  2. 源主機的flanneld服務將本來的數據內容UDP封裝後根據本身的路由表投遞給目的節點的flanneld服務,數據到達之後被解包,而後直接進入目的節點的flannel0虛擬網卡,而後被轉發到目的主機的docker0虛擬網卡,最後就像本機容器通訊同樣由docker0路由到達目標容器。
  3. 使每一個結點上的容器分配的地址不衝突。Flannel經過Etcd分配了每一個節點可用的IP地址段後,再修改Docker的啓動參數。「--bip=X.X.X.X/X」這個參數,它限制了所在節點容器得到的IP範圍。

如上分所述,須要完成以下操做:

  • 啓動Etcd後臺進程
  • 在Etcd裏添加Flannel的配置
  • 啓動Flanneld後臺進程
  • 配置Docker的啓動參數
  • 重啓Docker後臺進程

三個組件的啓動順序是: etcd->flanned->docker.

master主機的配置

  1. 修改配置文件: /etc/etcd/etcd.conf, 參考修改以下(其中ip爲master主機IP):
ETCD_LISTEN_CLIENT_URLS="http://10.1.11.101:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://10.1.11.101:2379"
  • ETCD_LISTEN_CLIENT_URLS 對外提供服務的地址,客戶端會鏈接到這裏和 etcd 交互
  • ETCD_ADVERTISE_CLIENT_URLS 告知客戶端url, 也就是服務的url
  1. 從新啓動etcd服務,確認運行狀態:
systemctl restart etcd
  1. 確認修改無誤後,添加和flannel相關的初始設置:
etcdctl -C http://10.1.11.101:2379 set /flannel/network/config '{"Network": "192.168.0.0/16"}'

node 主機的配置

  1. 修改flannel配置 /etc/sysconfig/flanneld, 參考以下修改:
FLANNEL_ETCD_ENDPOINTS="http://master:2379"
FLANNEL_OPTIONS='-etcd-prefix="/flannel/network"'
  1. 修改 /lib/systemd/system/docker.service 在 [Service] 段內添加一行配置,也是讓docker讀取flanneld提供給docker的網路參數,參考修改以下:
EnvironmentFile=-/run/flannel/docker.env
  1. 添加Kubelet服務須要的啓動參數,修改配置文件,在配置文件/etc/sysconfig/docker 配置項 OPTIONS 中添加
--exec-opt native.cgroupdriver=systemd -H unix:///var/run/docker.sock
  • 可選參數:--insecure-registry=registry.localhost 制定自定義的docker registry
  1. 按照順序重啓服務
systemctl daemon-reload
systemctl restart flanneld
systemctl restart docker
  1. 其餘node節點主機作一樣操做,最後在全部節點各自運行一個docker容器實例,查看各個容器間網絡是否互通,若是一切順利,跨物理機的容器集羣網絡配置完成。

K8s的總體架構

Kubenetes總體架構以下圖所示,主要包括apiserver、scheduler、controller-manager、kubelet、proxy。

Kubenetes總體架構圖

  • etcd 負責集羣的協調和服務發現
  • master端運行三個組件:
  • apiserver:kubernetes系統的入口,封裝了核心對象的增刪改查操做,以RESTFul接口方式提供給外部客戶和內部組件調用。它維護的REST對象將持久化到etcd(一個分佈式強一致性的key/value存儲)。

  • scheduler:負責集羣的資源調度,爲新建的pod分配機器。

  • controller-manager:負責執行各類控制器,目前有兩類:

    • endpoint-controller:按期關聯service和pod(關聯信息由endpoint對象維護),保證service到pod的映射老是最新的。
    • replication-controller:按期關聯replicationController和pod,保證replicationController定義的複製數量與實際運行pod的數量老是一致。
  • minion端運行兩個組件:
  • kubelet:負責管控docker容器,如啓動/中止、監控運行狀態等。它會按期從etcd獲取分配到本機的pod,並根據pod信息啓動或中止相應的容器。同時,它也會接收apiserver的HTTP請求,彙報pod的運行狀態.
  • proxy:負責爲pod提供代理。它會按期從etcd獲取全部的service,並根據service信息建立代理。當某個客戶pod要訪問其餘pod時,訪問請求會通過本機proxy作轉發。

k8s部署和配置

在準備好快物理主機的集羣網絡後, 在master主機上安裝kubernetes-master,其他三臺節點主機安裝kubernetes-node

主機 安裝軟件
master kubernetes-master、kubernetes-common、kubernetes-client
node1 kubernetes-node、kubernetes-common
node2 kubernetes-node、kubernetes-common
node3 kubernetes-node、kubernetes-common

集羣架構

  • master: 運行服務 apiserver, controllerManager, scheduler
  • node1 : 運行服務 kubelet, proxy
  • node2 : 運行服務 kubelet, proxy
  • node3 : 運行服務 kubelet, proxy

kubernetes的安全認證

基於CA簽名的雙向證書的生成過程以下:

  • 建立CA根證書
  • 爲kube-apiserver生成一個證書,並用CA證書進行簽名,設置啓動參數
  • 根據k8s集羣數量,分別爲每一個主機生成一個證書,並用CA證書進行簽名,設置相應節點上的服務啓動參數
  1. 生成CA、私鑰、證書
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ca.key -out ca.crt -subj "/CN=master"
  • CA的CommonName 須要和運行kube-apiserver服務器的主機名一致.
  1. 建立apiServer的私鑰、服務端證書

建立證書配置文件 /etc/kubernetes/openssl.cnf ,在alt_names裏指定全部訪問服務時會使用的目標域名和IP; 由於SSL/TLS協議要求服務器地址需與CA簽署的服務器證書裏的subjectAltName信息一致

[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
DNS.5 = localhost
DNS.6 = master
IP.1 = 127.0.0.1
IP.2 = 192.168.1.1
IP.3 = 10.1.10.101

最後兩個IP分別是clusterIP取值範圍裏的第一個可用值、master機器的IP。 k8s會自動建立一個service和對應的endpoint,來爲集羣內的容器提供apiServer服務; service默認使用第一個可用的clusterIP做爲虛擬IP,放置於default名稱空間,名稱爲kubernetes,端口是443; openssl.cnf裏的DNS1~4就是從容器裏訪問這個service時會使用到的域名.

  1. 建立分配給apiServer的私鑰與證書
mkdir -pv /etc/kubernetes/ca/
cd /etc/kubernetes/ca/
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=master" -config ../openssl.cnf
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 9000 -extensions v3_req -extfile ../openssl.cnf
  • 由於 controllerManager、scheduler 和 apiservers運行在同一臺主機上,所以CommonName 爲master
  • 驗證證書: openssl verify -CAfile ca.crt server.crt
  1. 建立訪問apiServer的各個組件使用的客戶端證書
for NAME in client node1 node2 node3  
do
    openssl genrsa -out $NAME.key 2048
    openssl req -new -key $NAME.key -out $NAME.csr -subj "/CN=$NAME"
    openssl x509 -req -days 9000 -in $NAME.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out $NAME.crt 
done
  • 注意設置CN(CommonName) 要在k8s集羣中(client node1 node2 node3)域名解析生效
  • 驗證證書:openssl verify -CAfile ca.crt *.crt
  1. 集羣分發證書
  • 建立 /etc/kubernetes/kubeconfig 模板,各個客戶端組件服務的啓動參數須要用到 : "--kubeconfig=/etc/kubernetes/kubeconfig"
kubectl config set-cluster k8s-cluster --server=https://10.1.10.101:6443 --certificate-authority=/etc/kubernetes/ca/ca.crt 
kubectl config set-credentials default-admin --certificate-authority=/etc/kubernetes/ca/ca.crt --client-key=/etc/kubernetes/ca/client.key --client-certificate=/etc/kubernetes/ca/client.crt
kubectl config set-context default-system --cluster=k8s-cluster --user=default-admin
kubectl config use-context default-system
kubectl config view > /etc/kubernetes/kubeconfig

生成的配置文件內容以下:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/ca/ca.crt
    server: https://10.1.10.101:6443
  name: k8s-cluster
contexts:
- context:
    cluster: k8s-cluster
    user: default-admin
  name: default-system
current-context: default-system
kind: Config
preferences: {}
users:
- name: default-admin
  user:
    client-certificate: /etc/kubernetes/ca/client.crt
    client-key: /etc/kubernetes/ca/client.key
  • 最後須要分發給各個主機的證書、KEY文件和對應的配置文件
/etc/kubernetes/kubeconfig : 全部主機的共用配置文件
ca.crt                     : CA根證書
client.key client.crt      : 提供給運行在k8s-master主機上的controllerManager、scheduler服務和kubectl工具使用   
node1.key node1.crt        : 提供給運行在node1主機上的kubelet, proxy服務使用
node2.key node2.crt        : 提供給運行在node2主機上的kubelet, proxy服務使用
node3.key node3.crt        : 提供給運行在node3主機上的kubelet, proxy服務使用
  • 由於controllerManager、scheduler 運行在master主機上,直接使用client.key client.crt
/etc/kubernetes/kubeconfig -> master 主機: /etc/kubernetes/kubeconfig
ca.crt    ->               master 主機: /etc/kubernetes/ca/ca.crt
node1.crt ->               master 主機: /etc/kubernetes/ca/client.crt
node1.key ->               master 主機: /etc/kubernetes/ca/client.key
  • node主機須要把對應證書拷貝到對應目錄和重命名文件,以node1主機爲例,操做以下,餘下類同:
/etc/kubernetes/kubeconfig -> node1 主機: /etc/kubernetes/kubeconfig
ca.crt    ->               node1 主機: /etc/kubernetes/ca/ca.crt
node1.crt ->               node1 主機: /etc/kubernetes/ca/client.crt
node1.key ->               node1 主機: /etc/kubernetes/ca/client.key
  • 每臺主機存放的證書位置以下,和kubeconfig配置中須要保持一致
/etc/kubernetes/kubeconfig
/etc/kubernetes/ca/ca.crt
/etc/kubernetes/ca/client.crt
/etc/kubernetes/ca/client.key
  • 由於自建的CA的根證書默認是不被k8s組件信任的,全部主機須要將CA根證書添加到信任列表
  1. 安裝 ca-certificates package: yum install ca-certificates
  2. 啓用dynamic CA configuration feature: update-ca-trust force-enable
  3. 新增長一個可信的根證書 cp /etc/kubernetes/ca/ca.crt /etc/pki/ca-trust/source/anchors/
  4. 更新列表: update-ca-trust extract

k8s的公共配置

/etc/kubernetes/config 配置記錄的全部組件的公共配置,如下服務啓動的時候都用到:

  • kube-apiserver
  • kube-controller-manager
  • kube-scheduler
  • kubelet
  • kube-proxy

/etc/kubernetes/config 內容以下:

KUBE_MASTER="--master=https://10.1.10.101:6443"
KUBE_CONFIG="--kubeconfig=/etc/kubernetes/kubeconfig"
KUBE_COMMON_ARGS="--logtostderr=true --v=1"

k8s-master的配置

  • 修改 kube-api-server 服務配置文件 /etc/kubernetes/apiserver :
KUBE_ETCD_SERVERS="--storage-backend=etcd3 --etcd-servers=http://10.1.10.101:2379"
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
KUBE_API_ARGS="--service-node-port-range=80-65535 --service-cluster-ip-range=192.168.1.0/16 --bind-address=0.0.0.0 --insecure-port=0 --secure-port=6443 --client-ca-file=/etc/kubernetes/ca/ca.crt --tls-cert-file=/etc/kubernetes/ca/server.crt --tls-private-key-file=/etc/kubernetes/ca/server.key"
  • 這裏監聽SSL/TLS的端口是6443;若指定小於1024的端口,有可能會致使啓動apiServer啓動失敗

  • 在master機器上,默認開8080端口提供未加密的HTTP服務,能夠經過--insecure-port=0 參數來關閉

  • 修改 kube-controller-manager 服務配置文件 /etc/kubernetes/controller-manager

KUBE_CONTROLLER_MANAGER_ARGS="--cluster-signing-cert-file=/etc/kubernetes/ca/server.crt --cluster-signing-key-file=/etc/kubernetes/ca/server.key --root-ca-file=/etc/kubernetes/ca/ca.crt --kubeconfig=/etc/kubernetes/kubeconfig"
  • 修改 kube-scheduler 服務配置文件 /etc/kubernetes/scheduler
KUBE_SCHEDULER_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig"
  • 完成配置後重啓master服務:
systemctl restart kube-apiserver
systemctl restart kube-controller-manager
systemctl restart kube-scheduler

k8s-node的配置

以node1主機爲例,其他主機類同

  • 修改 kubelet 服務配置文件 /etc/kubernetes/kubelet
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_HOSTNAME="--hostname-override=node1"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=docker.io/tianyebj/pod-infrastructure"
KUBELET_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig --cgroup-driver=systemd --fail-swap-on=false --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice"
  • 修改 kube-proxy 服務配置文件 /etc/kubernetes/proxy
KUBE_PROXY_ARG="--kubeconfig=/etc/kubernetes/kubeconfig"
  • 完成配置後重啓node服務:
systemctl restart kubelet
systemctl restart kube-proxy
  • 最後驗證節點運行狀態
kubectl --kubeconfig=/etc/kubernetes/kubeconfig get nodes

k8s 的操做和管理

  1. 建立nginx實例配置 nginx-rc-v1.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-v1 
  version: v1
spec:
  replicas: 3
  selector:
    app: nginx
    version: v1
  template:
    metadata:
      labels:
        app: nginx
        version: v1 
    spec:
      containers:
        - name: nginx
          image: nginx:v1 
          ports:
            - containerPort: 80
  1. 建立nginx對應的服務配置 nginx-src.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx 
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 80 
  selector:
      app: nginx
  1. 執行以下命令,完成一個nginx實例的部署
kubectl --kubeconfig=/etc/kubernetes/kubeconfig create -f nginx-rc-v1.yaml 
kubectl --kubeconfig=/etc/kubernetes/kubeconfig create -f nginx-srv.yaml
  1. 其餘操做參考
  • 擴容Replication Controller到副本數目4: kubectl --kubeconfig=/etc/kubernetes/kubeconfig cale rc nginx --replicas=4
  • 建立V2版本的Replication Controller配置文件nginx-rc-v2.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-v2 
  version: v2
spec:
  replicas: 4
  selector:
    app: nginx
    version: v2
  template:
    metadata:
      labels:
        app: nginx
        version: v2 
    spec:
      containers:
        - name: nginx
          image: nginx:v2 
          ports:
            - containerPort: 80
  • 以灰度升級方式從將 nginx pod 從V1版本升級到V2版本: kubectl --kubeconfig=/etc/kubernetes/kubeconfig rolling-update nginx-v2 -f nginx-rc-v2.yaml --update-period=10s

部分Kubernetes操做實例概念參考

  • Pods

Pod是Kubernetes的基本操做單元,把相關的一個或多個容器構成一個Pod,一般Pod裏的容器運行相同的應用。Pod包含的容器運行在同一個Minion(Host)上,看做一個統一管理單元,共享相同的volumes和network namespace/IP和Port空間。

  • Services

Services也是Kubernetes的基本操做單元,是真實應用服務的抽象,每個服務後面都有不少對應的容器來支持,經過Proxy的port和服務selector決定服務請求傳遞給後端提供服務的容器,對外表現爲一個單一訪問接口,外部不須要了解後端如何運行,這給擴展或維護後端帶來很大的好處。

  • Replication Controllers

Replication Controller確保任什麼時候候Kubernetes集羣中有指定數量的pod副本(replicas)在運行, 若是少於指定數量的pod副本(replicas),Replication Controller會啓動新的Container,反之會殺死多餘的以保證數量不變。Replication Controller使用預先定義的pod模板建立pods,一旦建立成功,pod 模板和建立的pods沒有任何關聯,能夠修改pod 模板而不會對已建立pods有任何影響,也能夠直接更新經過Replication Controller建立的pods。對於利用pod 模板建立的pods,Replication Controller根據label selector來關聯,經過修改pods的label能夠刪除對應的pods。Replication Controller主要有以下用法:

  1. Rescheduling :如上所述,Replication Controller會確保Kubernetes集羣中指定的pod副本(replicas)在運行, 即便在節點出錯時。
  2. Scaling :經過修改Replication Controller的副本(replicas)數量來水平擴展或者縮小運行的pods。
  3. Rolling updates :Replication Controller的設計原則使得能夠一個一個地替換pods來rolling updates服務。
  4. Multiple release :tracks: 若是須要在系統中運行multiple release的服務,Replication Controller使用labels來區分multiple release tracks。
  • Labels

Labels是用於區分Pod、Service、Replication Controller的key/value鍵值對,Pod、Service、 Replication Controller能夠有多個label,可是每一個label的key只能對應一個value。Labels是Service和Replication Controller運行的基礎,爲了將訪問Service的請求轉發給後端提供服務的多個容器,正是經過標識容器的labels來選擇正確的容器。一樣,Replication Controller也使用labels來管理經過pod 模板建立的一組容器,這樣Replication Controller能夠更加容易,方便地管理多個容器,不管有多少容器。

文檔參考

相關文章
相關標籤/搜索