容器化技術(No.2) -- Kubernetes 基礎

前言

今天的分享主要有以下幾個目標:

  • 瞭解什麼是 Kubernetes, 架構組成及核心概念
  • 可以通過 kubeadm 獨立搭建完整的集羣
  • 嘗試使用 kubectl 命令操作集羣
  • 學習使用 YAML 編排簡單任務

Docker 回顧

  • 什麼是 Docker?
- 打包代碼及其所有依賴項的軟件的標準單元, 本質上是宿主機上的一個進程;
- 通過 namespace 實現了資源隔離, 通過 cgroups 實現了資源限制, 通過 copy-on-write 機制實現了高效的文件操作
- 與虛擬機相比, Docker 啓動速度更快, 性能接近原生 (虛擬機損失 5% 左右), 資源使用更少

容器化技術(No.1) – Docker 基礎

  • 思考:
  • 什麼是 Kubernetes
  • 爲什麼要用 Kubernetes
  • Kubernetes 架構組成
  • Kubernetes 基本概念

Kubernetes

  • Kubernetes 是 Google 在 2014 年開源的一個容器集羣管理系統, 簡稱 K8S.
  • Kubernetes 用於容器化應用程序的部署, 擴展和管理, 目標是讓部署容器化應用簡單高效.

官方網站:http://www.kubernetes.io

技術架構及核心概念

技術架構

Kubernetes-Arch.png

Master

  • kube-apiserver

Kubernetes API, 集羣的統一入口, 通過 api server 控制着這些資源的訪問權限,通過使用暴露給外部用戶REST API接口執行對Kubernetes資源的CRUD操作, 處理後再提交給 Etcd 存儲.

  • kube-controller-manager

處理集羣中常規後臺任務, 一個資源對應一個控制器, 而ControllerManager就是負責管理這些控制器的.

  • kube-scheduler

根據調度算法爲新創建的Pod選擇一個Node節點, 可以任意部署,可以部署在同一個節點上,也可以部署在不同的節點上.

  • etcd

分佈式鍵值存儲系統.用於保存集羣狀態數據, 比如Pod、Service等對象信息.

Worker

  • kubelet

kubelet是Master在Node節點上的Agent, 管理本機運行容器的生命週期, 比如創建容器、Pod掛載數據卷、下載secret、獲取容器和節點狀態等工作.kubelet將每個Pod轉換成一組容器.

  • kube-proxy

在Node節點上實現Pod網絡代理, 維護網絡規則和四層負載均衡工作. 主要作用就是負責 service 的實.

  • docker

容器引擎, 運行容器.

核心概念

Pod

  • 最小部署單元
  • 一組容器的集合
  • 一個Pod中的容器共享網絡命名空間
  • Pod是短暫的

Controllers

  • Deployment : 無狀態應用部署
  • StatefulSet: 有狀態應用部署
  • DaemonSet : 確保所有 Node 運行相同的 Pod
  • Job : 一次性任務
  • Cronjob : 定時任務

控制器是更高級層次對象, 用於部署和管理 Pod.

Service

  • 防止 Pod 失聯
  • 定義一組 Pod 的訪問策略

Label

  • 標籤, 附加到某個資源上, 用於關聯對象、查詢和篩選

Namespaces

  • 命名空間, 將對象邏輯上隔離

基礎實踐

部署方式

官方提供三種部署方式:

  • minikube

Minikube是一個工具,可以在本地快速運行一個單點的Kubernetes,僅用於嘗試Kubernetes或日常開發的用戶使用。
部署地址:https://kubernetes.io/docs/setup/minikube

  • kubeadm

Kubeadm也是一個工具,提供kubeadm init和kubeadm join,用於快速部署Kubernetes集羣。
部署地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm

  • 二進制

推薦,從官方下載發行版的二進制包,手動部署每個組件,組成Kubernetes集羣。
下載地址:https://github.com/kubernetes/kubernetes/releases

部署集羣

kubeadm是官方社區推出的一個用於快速部署kubernetes集羣的工具.

這個工具能通過兩條指令完成一個kubernetes集羣的部署:

# 創建一個 Master 節點
$ kubeadm init

# 將一個 Node 節點加入到當前集羣中
$ kubeadm join <Master節點的IP和端口 >
安裝要求

在開始之前, 部署Kubernetes集羣機器需要滿足以下幾個條件:

  • 一臺或多臺機器, 操作系統 CentOS7.x-86_x64
  • 硬件配置:>=2GB mem, >=2 core, >=30GB disk
  • 集羣中所有機器之間網絡互通
  • 可以訪問外網, 需要拉取鏡像
  • 禁止swap分區
準備環境
角色 IP
k8s-master 192.168.0.10
k8s-node1 192.168.0.11
k8s-node2 192.168.0.12
#關閉防火牆
$ systemctl stop firewalld
$ systemctl disable firewalld

#關閉selinux
$ sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
$ setenforce 0  # 臨時

#關閉swap
$ swapoff -a  # 臨時
$ vim /etc/fstab  # 永久

#設置主機名
$ hostnamectl set-hostname <hostname>

#在master添加hosts
$ cat >> /etc/hosts << EOF
192.168.0.1 k8s-master
192.168.0.2 k8s-node1
192.168.0.3 k8s-node2
EOF

#將橋接的IPv4流量傳遞到iptables的鏈
$ cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sysctl --system  # 生效

#時間同步
$ yum install ntpdate -y
$ ntpdate -u cn.ntp.org.cn
所有節點安裝Docker/kubeadm/kubelet

Kubernetes 默認 CRI(容器運行時)爲 Docker, 因此先安裝 Docker.

1、 安裝Docker

$ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
$ yum install -y docker-ce-18.09.9-3.el7 
$ systemctl enable docker && systemctl start docker
$ docker --version
# cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF

2、 添加阿里雲 YUM 軟件源

$ cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

3、 安裝 kubeadm, kubelet 和 kubectl
由於版本更新頻繁, 這裏指定版本號部署:

$ yum install -y kubelet-1.16.2 kubeadm-1.16.2 kubectl-1.16.2
$ systemctl enable kubelet
部署 Kubernetes Master

在192.168.0.10(Master)執行.

$ kubeadm init \
  --apiserver-advertise-address=192.168.0.10 \
  --image-repository registry.aliyuncs.com/google_containers \
  --kubernetes-version v1.16.2 \
  --service-cidr=10.96.0.0/12 \
  --pod-network-cidr=10.244.0.0/16

kubeadm 到底做了什麼? 稍後說明.

由於默認拉取鏡像地址k8s.gcr.io國內無法訪問, 這裏指定阿里雲鏡像倉庫地址.

使用kubectl工具:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
$ kubectl get nodes
安裝Pod網絡插件(CNI)
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

確保能夠訪問到quay.io這個registery.

加入Kubernetes Node

在192.168.0.11/12(Worker)執行.

向集羣添加新節點, 執行在kubeadm init輸出的kubeadm join命令:

$ kubeadm join 192.168.0.10:6443 --token i1ofj9.ujm6xpc7sx4tmt1c \
    --discovery-token-ca-cert-hash sha256:7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9

默認token有效期爲24小時, 超時就需要重新創建token, 操作如下:

# Master 節點執行
$ kubeadm token create
i1ofj9.ujm6xpc7sx4tmt1c
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9
# Worker 上執行
$ kubeadm join 192.168.0.10:6443 --token i1ofj9.ujm6xpc7sx4tmt1c --discovery-token-ca-cert-hash sha256:7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9

也可以通過如下命令直接獲取

$ kubeadm token create --print-join-command

官方文檔: https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-join

測試kubernetes集羣

在Kubernetes集羣中創建一個pod, 驗證是否正常運行:

$ kubectl create deployment nginx --image=nginx
$ kubectl expose deployment nginx --port=80 --type=NodePort
$ kubectl get pod,svc

訪問地址:http://NodeIP:Port

部署 Dashboard
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml

默認Dashboard只能集羣內部訪問, 修改Service爲NodePort類型, 暴露到外部:

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard

訪問地址:http://NodeIP:Port

創建service account並綁定默認cluster-admin管理員集羣角色:

kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

使用輸出的token登錄Dashboard.

kubeadm init 到底做了些什麼
[root@Ali-irvin ~]# kubeadm init \
>   --apiserver-advertise-address=192.168.0.10 \
>   --image-repository registry.aliyuncs.com/google_containers \
>   --kubernetes-version v1.16.2 \
>   --service-cidr=10.96.0.0/12 \
>   --pod-network-cidr=10.244.0.0/16
[init] Using Kubernetes version: v1.16.
# 1. 環境檢查
[preflight] Running pre-flight checks       
	[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
# 2. 下載鏡像
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
# 3. 爲 kubelet 創建配置文件並啓動
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
# 4. 爲apiserver、etcd生成https證書
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [ali-irvin kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.0.10]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [ali-irvin localhost] and IPs [192.168.0.10 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [ali-irvin localhost] and IPs [192.168.0.10 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
# 5. 生成連接apiserver的kubeconfig文件
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
# 6. 容器啓動 master 組件
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 18.002987 seconds
# 7. 將涉及的配置文件存儲到 configmap
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.16" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
# 8. 設置 master 節點不可調度 Pod
[mark-control-plane] Marking the node ali-irvin as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node ali-irvin as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
# 9. 啓用 bootstrap 自動爲 kubelet 頒發證書
[bootstrap-token] Using token: i1ofj9.ujm6xpc7sx4tmt1c
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
# 10. 安裝插件:CoreDNS、kube-proxy
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.0.10:6443 --token i1ofj9.ujm6xpc7sx4tmt1c \
    --discovery-token-ca-cert-hash sha256:7ce38ff560c14aa85e2ae1736c081019b9890c78aee86cd75c4ff1ef311d6aa9
[root@Ali-irvin ~]#
1、檢查系統環境是否滿足,例如swap是否關閉、配置是否滿足
2、下載所需鏡像,kubeadm config images pull
3、爲 kubelet 創建配置文件並啓動
4、爲 apiserver、etcd 生成 https 證書(/etc/kubernetes/pki/)
5、生成連接 apiserver 的 kubeconfig 文件
6、容器啓動 master 組件
7、將涉及的配置文件存儲到 configmap
8、設置 master 節點不可調度 Pod
9、啓用 bootstrap 自動爲 kubelet 頒發證書
10、安裝插件:CoreDNS、kube-proxy

常見問題

1. 證書問題

問題: 僅火狐瀏覽器可訪問 Dashboard

原因: 官方提供的字簽證書有問題(有效時間)

解決方案:

  1. 刪除默認的secret
  2. 用自簽證書創建新的secret
  3. 修改 dashboard.yaml 文件

2. token 失效

$ kubeadm token create --print-join-command

3. 環境清理

$ kubeadm reset

命令行操作

kubectl --help 查看幫助信息

kubectl create --help 查看 create 命令幫助信息

命令 描述
create 通過文件名或標準輸入創建資源
expose 將一個資源公開爲一個新的Service
run 在集羣中運行一個特定的鏡像
set 在對象上設置特定的功能
get 顯示一個或多個資源
explain 文檔參考資料
edit 使用默認的編輯器編輯一個資源.
delete 通過文件名、標準輸入、資源名稱或標籤選擇器來刪除資源.
rollout 管理資源的發佈
rolling-update 對給定的複製控制器滾動更新
scale 擴容或縮容Pod數量, Deployment、ReplicaSet、RC或Job
autoscale 創建一個自動選擇擴容或縮容並設置Pod數量
certificate 修改證書資源
cluster-info 顯示集羣信息
top 顯示資源(CPU/Memory/Storage)使用.需要Heapster運行
cordon 標記節點不可調度
uncordon 標記節點可調度
drain 驅逐節點上的應用, 準備下線維護
taint 修改節點taint標記
describe 顯示特定資源或資源組的詳細信息
logs 在一個Pod中打印一個容器日誌.如果Pod只有一個容器, 容器名稱是可選的
attach 附加到一個運行的容器
exec 執行命令到容器
port-forward 轉發一個或多個本地端口到一個pod
proxy 運行一個proxy到Kubernetes API server
cp 拷貝文件或目錄到容器中
auth 檢查授權
apply 通過文件名或標準輸入對資源應用配置
patch 使用補丁修改、更新資源的字段
replace 通過文件名或標準輸入替換一個資源
convert 不同的API版本之間轉換配置文件
label 更新資源上的標籤
annotate 更新資源上的註釋
completion 用於實現kubectl工具自動補全
api-versions 打印受支持的API版本
config 修改kubeconfig文件(用於訪問API, 比如配置認證信息)
help 所有命令幫助
plugin 運行一個命令行插件
version 打印客戶端和服務版本信息

使用kubectl管理應用生命週期

# 創建
$ kubectl create deployment web --image=java 
$ kubectl get deploy,pods

# 發佈
$ kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web
$ kubectl get service

# 升級
$ kubectl set image deployment/web nginx=nginx:1.15
$ kubectl rollout status deployment/nginx-deployment  # 查看升級狀態

# 回滾
$ kubectl rollout history deployment/web  # 查看發佈記錄
$ kubectl rollout undo deployment/web   # 回滾最新版本
$ kubectl rollout undo deployment/web --revision=2  # 回滾指定版本

# 刪除
$ kubectl delete deploy/web
$ kubectl delete svc/web

常用選項

-f, --filename=[]: 文件名、目錄、或者URL創建資源
-o, --output='': json|yaml|name|wide   所有查看的資源都可以用
-l, --selector='': 根據標籤過濾內容,支持運算符 '=', '==','!='.(示例 -l key1=value1,key2=value2)

資源編排

編寫YAML注意事項

YAML 是一種簡潔的非標記語言.

語法格式:

  • 縮進表示層級關係
  • 不支持製表符“tab”縮進, 使用空格縮進
  • 通常開頭縮進 2 個空格
  • 字符後縮進 1 個空格, 如冒號、逗號等
  • “—” 表示YAML格式, 一個文件的開始
  • “#”註釋
YAML內容解析

YAML 編排文件內容大致分爲兩部分:

# 控制器相關定義
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLables:
      app: nginx
# 被控制對象定義
    template:
      metadata:
        lables:
          app: nginx
      spec:
        containers:
        - name: nginx
          image: nginx:latest
          ports:
          - containerPort:80

控制器定義:定義控制器屬性
被控制對象:Pod 模板, 定義容器屬性

具體字段意義:

apiVersion API版本
kind 資源類型
metadata 資源元數據
spec 資源規格
replicas 副本數量
selector 標籤選擇器
template Pod模板
metadata Pod元數據
spec Pod規格
containers 容器配置
**編寫 YAML **

熟能生巧, 多寫. 另外可通過如下方式快速生成, 基於實際場景修改.

  • run 命令生成部署模板

    kubectl create deployment nginx --image=nginx:1.14 -o yaml --dry-run> my-deploy.yaml

  • get 命令將已有部署的應用yaml導出

    kubectl get my-deploy/nginx -o=yaml --export > my-deploy.yaml

  • 通過 explain 查看更詳細的幫助文檔獲得

    kubectl explain pods.spec.containers

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