如何在CentOS上建立Kubernetes叢集

騰訊雲加社群發表於2018-08-06

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~

本文由程式設計男孩 發表於雲+社群專欄

介紹

Kubernetes(常簡稱為K8s)是用於自動部署、擴充套件和管理容器化(containerized)應用程式的開源系統。Google設計並捐贈給Linux基金會來使用的。它旨在提供“跨主機叢集的自動部署、擴充套件以及執行應用程式容器的平臺”。它支援一系列容器工具, 包括Docker等。

Kubeadm是 Kubernetes 官方推出的部署工具 ,例如API伺服器,Controller Manager和Kube DNS,該工具實作類似Docker swarm 一樣的部署方式,透過初始化Master 節點來提供給Node快速加入。但是,它的缺點也很明顯,它不會建立使用者或處理作業系統級依賴關係及其配置的安裝。對於這些步驟,可以使用AnsibleSaltStack等配置管理工具。使用這些工具可以更輕鬆地更改其他叢集或重新建立現有叢集。

在本教程中,您將使用Ansible和Kubeadm從頭開始設定Kubernetes叢集,然後給它部署一個容器化的Nginx程式。

目標

您的群集將包含以下物理資源:

  • 一個主節點

主節點(Kubernetes中的節點指的是伺服器)負責管理叢集的狀態。我們將用它執行Etcd,該伺服器目的是將工作負載排程到工作節點的元件之間儲存叢集資料。

  • 兩個工作節點

工作節點是執行工作負載(即容器化應用程式和服務)的伺服器。一旦工作節點分配了工作負載,工作節點將繼續執行您的工作負載,即使計劃在排程完成後停止工作也是如此。通過新增工作節點可以增加群集的容量。

完成本教程後,您將擁有一個可以執行容器化應用程式的叢集,前提是叢集中的伺服器具有足夠的CPU和RAM資源供應用程式使用。幾乎任何傳統的Unix應用程式(包括Web應用程式,資料庫,守護程式和命令列工具)都可以進行容器化,並在叢集上執行。群集本身將在每個節點上消耗大約300-500MB的記憶體和10%的CPU。

設定群集後,您將部署Web伺服器Nginx以確保它正確執行。

準備

  • 本地Linux / macOS /BSD計算機上的SSH金鑰對。如果您之前沒有使用過SSH金鑰,同時使用的是騰訊雲的伺服器的話,請參考建立 SSH 金鑰文件。如果您使用的不是騰訊雲的伺服器,請自行搜尋,本文暫不涉及。本教程的本地計算機是Linux作業系統,請勿使用Windows進行試驗。
  • 執行CentOS 7的三臺伺服器,記憶體至少為1GB。沒有伺服器的同學可以在這裡購買,不過我個人更推薦您使用免費的騰訊雲開發者實驗室進行試驗,學會安裝後在購買伺服器。您應該能夠以SSH金鑰對的root使用者身份SSH到每個伺服器。請務必將您的公鑰新增到主節點上的centos使用者帳戶。如果您需要有關向特定使用者帳戶新增SSH金鑰的指導,請參閱金鑰繫結/解綁伺服器文件。
  • Ansible需要安裝在您的本地計算機上。有關安裝說明,請按照Ansible官方安裝文件
  • 瞭解如何從Docker映象啟動容器。如果需要複習,請參閱如何安裝使用Docker的“第5步 - 執行Docker容器” 。

第1步 - 設定工作區目錄和Ansible配置

在本節中,您將在本地計算機上建立一個用作工作區的目錄。您還將在本地配置Ansible,以便它可以與遠端伺服器上的命令進行通訊。為此,您將建立一個hosts檔案包,其包含例如伺服器的IP地址和每個伺服器所屬的組等資訊。

在三臺伺服器中,一臺伺服器將作為主伺服器master_ip。另外兩臺伺服器則是是工作節點,並擁有IPworker_1_ipworker_2_ip

在本地計算機的主目錄中建立一個名為~/kube-cluster/hosts的目錄並進入其中:

mkdir ~/kube-cluster
cd ~/kube-cluster
複製程式碼

該目錄將是本教程的工作區,包含所有Ansible設定。它也將是您執行所有本地命令的目錄。

使用vi命令建立一個名為~/kube-cluster/hosts的檔案或用您最喜歡的文字編輯器:

vi ~/kube-cluster/hosts
複製程式碼

i將以下文字插入到檔案中,該檔案將指定有關群集邏輯結構的資訊:

[masters]
master ansible_host=master_ip ansible_user=root

[workers]
worker1 ansible_host=worker_1_ip ansible_user=root
worker2 ansible_host=worker_2_ip ansible_user=root
複製程式碼

完成後,按,ESC然後輸入:wq將更改寫入檔案並退出。

您可能還記得在Ansible中用於指定伺服器資訊的庫存檔案,例如IP地址,遠端使用者和伺服器分組,以作為執行命令的單個單元進行目標。~/kube-cluster/hosts將是您的庫存檔案,並且您已向其新增了兩個Ansible組(主伺服器工作伺服器),用於指定叢集的邏輯結構。

伺服器組中,有一個名為“master”的伺服器,其中列出了主節點的IP(master_ip),並指定Ansible應以根使用者身份執行遠端命令。

同樣,在workers組中,有兩個工作伺服器(worker_1_ipworker_2_ip),它們也需要指定ansible_user為root使用者。

在設定伺服器清單之後,讓我們繼續安裝作業系統級依賴關係並建立配置設定。

第2步 - 安裝Kubernetes的依賴項

在本節中,您將使用CentOS的yum軟體包管理器安裝Kubernetes所需的軟體包。這些包是:

  • Docker - 容器執行時。這是執行容器的元件。Kubernetes正在積極開發對rkt等其他執行容器服務的支援。
  • kubeadm - CLI工具,以標準方式安裝和配置群集的各個元件。
  • kubelet - 在所有節點上執行並處理節點級操作的系統服務/程式。
  • kubectl- 通過其API伺服器向叢集發出命令的CLI工具。

建立工作空間中指定的檔案vi ~/kube-cluster/kube-dependencies.yml

vi ~/kube-cluster/kube-dependencies.yml
複製程式碼

將下面的內容插到檔案內:

- hosts: all
  become: yes
  tasks:
   - name: install Docker
     yum:
       name: docker
       state: present
       update_cache: true

   - name: start Docker
     service:
       name: docker
       state: started

   - name: disable SELinux
     command: setenforce 0

   - name: disable SELinux on reboot
     selinux:
       state: disabled

   - name: ensure net.bridge.bridge-nf-call-ip6tables is set to 1
     sysctl:
      name: net.bridge.bridge-nf-call-ip6tables
      value: 1
      state: present

   - name: ensure net.bridge.bridge-nf-call-iptables is set to 1
     sysctl:
      name: net.bridge.bridge-nf-call-iptables
      value: 1
      state: present

   - name: add Kubernetes' YUM repository
     yum_repository:
      name: Kubernetes
      description: Kubernetes YUM repository
      baseurl: https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
      gpgkey: https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
      gpgcheck: yes

   - name: install kubelet
     yum:
        name: kubelet
        state: present
        update_cache: true

   - name: install kubeadm
     yum:
        name: kubeadm
        state: present

   - name: start kubelet
     service:
       name: kubelet
       enabled: yes
       state: started

- hosts: master
  become: yes
  tasks:
   - name: install kubectl
     yum:
        name: kubectl
        state: present
複製程式碼

檔案中的的第一部分內容如下:

  • 容器執行時,安裝Docker。
  • 啟動Docker服務。
  • 請禁用SELinux,因為Kubernetes尚未完全支援它。
  • 設定網路所需的一些與netfilter相關的sysctl值。這將允許Kubernetes設定iptables規則,以便在節點上接收橋接的IPv4和IPv6網路流量。
  • 將Kubernetes YUM儲存庫新增到遠端伺服器的儲存庫列表中。
  • 安裝kubeletkubeadm

第二部分意思是在主節點上設定一下kubectl的任務。

完成後儲存並關閉檔案。

接下來,執行playbook

ansible-playbook -i hosts ~/kube-cluster/kube-dependencies.yml
複製程式碼

完成後,您將看到類似於以下內容的輸出:

PLAY [all] ****

TASK [Gathering Facts] ****
ok: [worker1]
ok: [worker2]
ok: [master]

TASK [install Docker] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [disable SELinux] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [disable SELinux on reboot] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [ensure net.bridge.bridge-nf-call-ip6tables is set to 1] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [ensure net.bridge.bridge-nf-call-iptables is set to 1] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [start Docker] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [add Kubernetes' YUM repository] *****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [install kubelet] *****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [install kubeadm] *****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [start kubelet] ****
changed: [master]
changed: [worker1]
changed: [worker2]

PLAY [master] *****

TASK [Gathering Facts] *****
ok: [master]

TASK [install kubectl] ******
ok: [master]

PLAY RECAP ****
master                     : ok=9    changed=5    unreachable=0    failed=0   
worker1                    : ok=7    changed=5    unreachable=0    failed=0  
worker2                    : ok=7    changed=5    unreachable=0    failed=0  
複製程式碼

執行後,Docker,kubeadmkubelet將安裝在所有遠端服務。kubectl不是必需元件,僅用於執行叢集命令。但是我們建議您還是安裝它,因為您將僅從主節點執行kubectl命令。

現在安裝了所有系統依賴項。讓我們設定主節點並初始化叢集。

第3步 - 設定主節點

在本節中,您將設定主節點。然而在建立配置之前,我們需要熟悉幾個概念,如PodsPod 網路外掛

Kubernetes的基本排程單元稱為“pods”。它可以把更高階別的抽象內容增加到容器化元件。一個pod一般包含一個或多個容器,這樣可以保證它們一直位於主機上,並且可以共享資源。Kubernetes中的每個pod都被分配一個唯一的(在叢集內的)IP地址這樣就可以允許應用程式使用埠,而不會有衝突的風險。Pod可以定義一個卷,例如本地磁碟目錄或網路磁碟,並將其暴露在pod中的一個容器之中。pod可以通過Kubernetes API手動管理,也可以委託給控制器來管理。

每個pod都有自己的IP地址,一個節點上的pod應該能夠使用pod的IP訪問另一個節點上的pod。單個節點上的容器可以通過本地介面輕鬆進行通訊。然而,pod之間的通訊更復雜,並且需要單獨的網路元件,該元件可以透明地將流量從一個節點上的pod傳送到另一個節點上的pod。此功能由pod網路外掛提供。對於這個群集,建議您將使用Flannel選項

在本地計算機上建立一個命名為master.yml的Ansible playbook :

vi ~/kube-cluster/master.yml
複製程式碼

將以下內容新增到檔案中以初始化叢集並安裝Flannel:

- hosts: master
  become: yes
  tasks:
    - name: initialize the cluster
      shell: kubeadm init --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt
      args:
        chdir: $HOME
        creates: cluster_initialized.txt

    - name: create .kube directory
      become: yes
      become_user: centos
      file:
        path: $HOME/.kube
        state: directory
        mode: 0755

    - name: copy admin.conf to user's kube config
      copy:
        src: /etc/kubernetes/admin.conf
        dest: /home/centos/.kube/config
        remote_src: yes
        owner: centos

    - name: install Pod network
      become: yes
      become_user: centos
      shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml >> pod_network_setup.txt
      args:
        chdir: $HOME
        creates: pod_network_setup.txt
複製程式碼

這是上面內容的詳解:

  • 第一個任務通過執行kubeadm init初始化叢集。傳遞--pod-network-cidr=10.244.0.0/16引數指定將從中分配pod IP的私有子網。Flannel預設使用上述子網,我們告訴kubeadm使用相同的子網。
  • 第二個任務建立一個.kube目錄在/home/centos。此目錄將儲存配置資訊,例如連線到群集所需的管理金鑰檔案以及群集的API地址。
  • 第三個任務將/etc/kubernetes/admin.conf生成的檔案複製kubeadm initcentos使用者的主目錄。這將允許您用kubectl訪問新建立的群集。
  • 最後一個任務執行kubectl apply安裝Flannelkubectl apply -f descriptor.[yml|json]是告訴kubectl建立descriptor.[yml|json]檔案中描述的物件的語法。kube-flannel.yml檔案包含Flannel在群集中設定所需的物件的說明。

完成後儲存並關閉檔案。執行配置:

ansible-playbook -i hosts ~/kube-cluster/master.yml
複製程式碼

完成後,您將看到類似於以下內容的輸出:

PLAY [master] ****

TASK [Gathering Facts] ****
ok: [master]

TASK [initialize the cluster] ****
changed: [master]

TASK [create .kube directory] ****
changed: [master]

TASK [copy admin.conf to user's kube config] *****
changed: [master]

TASK [install Pod network] *****
changed: [master]

PLAY RECAP ****
master                     : ok=5    changed=4    unreachable=0    failed=0  
複製程式碼

要檢查主節點的狀態,請使用以下命令通過SSH連線到該節點:

ssh centos@master_ip
複製程式碼

進入主節點後,執行:

kubectl get nodes
複製程式碼

您現在將看到以下輸出:

NAME      STATUS    ROLES     AGE       VERSION
master    Ready     master    1d        v1.10.1
複製程式碼

輸出表明master節點已完成所有初始化任務,並且處於Ready可以開始接受工作節點並執行傳送到API伺服器的任務的狀態。您現在可以從本地計算機新增工作程式。

第4步 - 設定工作節點

將工作程式新增到叢集涉及在每個叢集上執行單個命令。此命令包括必要的群集資訊,例如主伺服器API伺服器的IP地址和埠以及安全令牌。只有傳入安全令牌的節點才能加入群集。

f反回您的工作區並建立一個名為workers.yml的配置:

vi ~/kube-cluster/workers.yml
複製程式碼

將以下文字新增到檔案中:

- hosts: master
  become: yes
  gather_facts: false
  tasks:
    - name: get join command
      shell: kubeadm token create --print-join-command
      register: join_command_raw

    - name: set join command
      set_fact:
        join_command: "{{ join_command_raw.stdout_lines[0] }}"


- hosts: workers
  become: yes
  tasks:
    - name: join cluster
      shell: "{{ hostvars['master'].join_command }} >> node_joined.txt"
      args:
        chdir: $HOME
        creates: node_joined.txt
複製程式碼

以下是配置的作用:

  • 第一個配置獲取join命令,以便在worker節點上執行。該命令將採用以下格式:kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>一旦它獲得具有的令牌雜湊值的命令,該任務就將其設定為可用,以便下一個配置能夠訪問該資訊。
  • 第二個配置有一個任務,它在所有工作節點上執行join命令。完成此任務後,兩個工作節點將成為群集的一部分。

完成後儲存並關閉檔案。執行配置:

ansible-playbook -i hosts ~/kube-cluster/workers.yml
複製程式碼

完成後,您將看到類似於以下內容的輸出:

PLAY [master] ****

TASK [get join command] ****
changed: [master]

TASK [set join command] *****
ok: [master]

PLAY [workers] *****

TASK [Gathering Facts] *****
ok: [worker1]
ok: [worker2]

TASK [join cluster] *****
changed: [worker1]
changed: [worker2]

PLAY RECAP *****
master                     : ok=2    changed=1    unreachable=0    failed=0   
worker1                    : ok=2    changed=1    unreachable=0    failed=0  
worker2                    : ok=2    changed=1    unreachable=0    failed=0  
複製程式碼

通過新增工作節點,您的群集現在已完全設定並正常執行,工作節點可以隨時執行工作負載。讓我們驗證群集是否按預期工作。

第5步 - 驗證群集

叢集有時可能在安裝過程中失敗,因為節點已關閉或主伺服器與工作伺服器之間的網路連線無法正常工作。讓我們驗證叢集並確保節點正常執行。

您需要從主節點檢查群集的當前狀態,以確保節點已準備就緒。如果從主節點斷開連線,則可以使用以下命令通過SSH將其重新連線到主節點:

ssh centos@master_ip
複製程式碼

然後執行以下命令以獲取叢集的狀態:

kubectl get nodes
複製程式碼

您將看到類似於以下內容的輸出:

NAME      STATUS    ROLES     AGE       VERSION
master    Ready     master    1d        v1.10.1
worker1   Ready     <none>    1d        v1.10.1 
worker2   Ready     <none>    1d        v1.10.1
複製程式碼

如果所有的節點都具有ReadySTATUS(狀態),這意味著它們是叢集的一部分,並準備執行工作負載。

但是,如果幾個節點擁有NotReadySTATUS(狀態),它可能意味著工作節點還沒有完成自己的設定。等待大約五到十分鐘再重新執行kubectl get node並檢查新輸出。如果一些節點仍具有NotReady狀態,則需要驗證並重新執行前面步驟中的命令。

現在您的叢集已成功驗證,讓我們在叢集上部署一個示例Nginx應用程式。

第6步 - 在群集上執行應用程式

您現在可以將任何容器化應用程式部署到您的群集。讓我們使用部署和服務部署Nginx,以瞭解如何將此應用程式部署到叢集。如果更改Docker映象名稱和任何相關標誌(例如portsvolumes),您也可以使用以下命令用於其他容器化應用程式。

在主節點內,執行以下命令以建立名為nginx的部署:

kubectl run nginx --image=nginx --port 80
複製程式碼

部署是一種Kubernetes物件,可確保始終根據已定義的模板執行指定數量的pod,即使pod在群集生命週期內崩潰也是如此。上面的部署將使用Docker映象庫的Nginx Docker Image建立一個包含一個容器的pod 。

接下來,執行以下命令以建立名為nginx將公開公共應用程式的服務。它將通過NodePort實現,該方案將通過在群集的每個節點上開啟的任意埠訪問pod:

kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort
複製程式碼

服務是另一種型別的Kubernetes物件,它向內部和外部客戶端公開叢集內部服務。它們還能夠對多個pod進行負載均衡請求,並且是Kubernetes中不可或缺的元件,經常與其他元件互動。

執行以下命令:

kubectl get services
複製程式碼

這將輸出類似於以下內容的文字:

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP           PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>                443/TCP        1d
nginx        NodePort    10.109.228.209   <none>                80:nginx_port/TCP   40m
複製程式碼

從上面輸出的第三行,您可以檢索執行Nginx的埠。Kubernetes將分配一個大於30000自動的隨機埠,同時確保該埠尚未受到其他服務的約束。

要測試一切正常,請訪問或通過本地計算機上的瀏覽器。您將看到Nginx熟悉的歡迎頁面。http://worker_1_ip:nginx_port或者http://worker_2_ip:nginx_port

如果要刪除Nginx應用程式,請先nginx從主節點刪除該服務:

kubectl delete service nginx
複製程式碼

執行以下命令以確保已刪除該服務:

kubectl get services
複製程式碼

您將看到以下輸出:

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP           PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>                443/TCP        1d
複製程式碼

然後刪除部署:

kubectl delete deployment nginx
複製程式碼

執行以下命令以確認這是否有效:

kubectl get deployments
複製程式碼
No resources found.

複製程式碼

結論

在本教程中,您已使用Kubeadm和Ansible成功在CentOS 7上設定Kubernetes叢集以實現自動化。

如果您想知道要在叢集設定的情況下如何處理叢集,那麼下一步就是將自己的應用程式和服務部署到叢集上。這是一個連結列表,其中包含可以指導您完成此過程的更多資訊:

  • Dockerizing應用程式 - 列出了詳細說明如何使用Docker對應用程式進行容器化的示例。
  • Pod概述 - 詳細描述了Pod如何工作以及它們與其他Kubernetes物件的關係。Pods在Kubernetes中無處不在,因此瞭解它們將有助於您的工作。
  • 部署概述 - 這提供了部署的概述。瞭解部署之類的控制器如何有效地工作,因為它們經常在無狀態應用程式中用於擴充套件和不健康應用程式的自動修復。
  • 服務概述 - 這包括服務,Kubernetes叢集中另一個常用物件。瞭解服務型別及其選項對於執行無狀態和有狀態應用程式至關重要。

其他重要概念是VolumesIngressesSecrets,所有這些在部署生產應用程式時都派上用場。Kubernetes提供了許多功能和特性。Kubernetes官方文件是瞭解概念,查詢特定於任務的教程以及查詢各種物件的API參考的最佳位置。更多Linux教程請前往騰訊雲+社群學習更多知識。


參考文獻: 《How To Create a Kubernetes 1.10 Cluster Using Kubeadm on CentOS 7》 《只要用 kubeadm 小朋友都能部署 Kubernetes》

問答

如何使用Kubernetes?

相關閱讀

安全報告 | 2018上半年網際網路惡意爬蟲分析:從全景視角看爬蟲與反爬蟲

安全報告 | SSH 暴力破解趨勢:從雲平臺向物聯網裝置遷移

給你的CVM安裝一個皮膚吧!

此文已由作者授權騰訊雲+社群釋出,原文連結:https://cloud.tencent.com/developer/article/1177930?fromSource=waitui

歡迎大家前往騰訊雲+社群或關注雲加社群微信公眾號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~

海量技術實踐經驗,盡在雲加社群

相關文章