天天看點

k8s叢集詳細安裝實錄

作者:香蕉你個拔剌
k8s叢集詳細安裝實錄

前言

k8s全稱kubernetes,是一個開源的容器編排引擎,用來對容器化應用進行自動化部署、 擴縮和管理。該項目托管在 CNCF。目前k8s已經成為發展最快、市場占有率最高的容器編排引擎産品,越來越多企業正在擁抱k8s,推動微服務、容器等熱門技術的普及和落地。

對于 k8s這項平台級技術,覆寫的技術範圍非常廣,包括了計算、網絡、存儲、高可用、監控、日志管理等多個方面。越是門檻高的知識,就越需要搭建一個最小可用系統,先把玩起來,快速了解基本概念、功能和使用場景,建立起對學習對象的感性認識。如果直接上來就學習理論知識和概念,很容易從入門到放棄。

0. 目錄

1. k8s基礎知識

2. 部署環境

3. CentOS初始化配置

4. Master節點配置

5. Worker節點配置

6. 使用k8s部署應用

7. 後記

8. 參考文獻

1. k8s基礎知識

k8s叢集是主從分布式架構,由Master Node和Worker Node組成,節點上運作着k8s元件服務。

k8s叢集詳細安裝實錄

Master 是 Cluster 的大腦,主要職責是排程,運作的 k8s 元件有kube-apiserver、kube-scheduler、kube-controller-manager、etcd 和 Pod 網絡(例如 flannel)。可以同時運作多個 Master實作高可用。

  • API Server(kube-apiserver):提供 HTTP/HTTPS RESTful API,實作認證、授權、通路控制、API注冊和發現等功能,各種用戶端工具(CLI 或 UI)以及 k8s 其他元件可以通過它管理 Cluster 資源。
  • Scheduler(kube-scheduler):負責決定将 Pod 放在哪個 Node 上運作。Scheduler 在排程時會充分考慮 Cluster 的拓撲結構、目前各個節點的負載以及應用對高可用、性能、資料親和性的需求。
  • Controller Manager(kube-controller-manager):負責管理 Cluster 各種資源,保證資源處于預期的狀态。Controller Manager 由多種 controller 組成,包括 replication controller、endpoints controller、namespace controller、serviceaccounts controller 等。不同的 controller 管理不同的資源。例如 replication controller 管理 Deployment、StatefulSet、DaemonSet 的生命周期,namespace controller 管理 Namespace 資源。
  • etcd :負責儲存 Cluster 的配置資訊和各種資源的狀态資訊。當資料發生變化時,etcd 會快速地通知 k8s相關元件。
  • Pod 網絡:Pod 是 k8s的最小工作單元。每個 Pod 包含一個或多個容器。Pod 中的容器會作為一個整體被 Master 排程到一個 Worker上運作。Pod 要能夠互相通信,Cluster 必須部署 Pod 網絡,flannel 是其中一個可選方案。

Worker是 Pod 運作的地方,k8s 支援 Docker、rkt 等容器 Runtime。Worker上運作的元件有 kubelet、kube-proxy 和 Pod 網絡。Worker 由 Master 管理,負責監控并向Master彙報容器的狀态,并根據 Master 的要求管理容器的生命周期。

  • kubelet:是 Worker的 agent,當 Scheduler 确定在某個 Worker上運作 Pod 後,會将 Pod 的具體配置資訊(image、volume 等)發送給該節點的 kubelet,kubelet 根據這些資訊建立和運作容器,并向 Master 報告運作狀态。
  • kube-proxy:service 在邏輯上代表了後端的多個 Pod,外界通過 service 通路 Pod。service 接收到的請求是如何轉發到 Pod 的呢?這就是 kube-proxy 要完成的工作。每個 Worker都會運作 kube-proxy 服務,負責将通路 service 的 TCP/UPD 資料流轉發到後端的容器。如果有多個副本,kube-proxy 會實作負載均衡。

2. 部署環境

本次實驗将搭建一個包含1個Master 節點 + 2個Worker 節點的k8s叢集環境。

作業系統版本:CentOS 7.9

k8s版本:1.20.15

docker版本:19.3.5

主機名 ip
k8s-master 10.10.10.128
k8s-worker1 10.10.10.131
k8s-worker2 10.10.10.132

3. CentOS初始化配置

TIPS:本次實驗準備了3台CentOS 虛拟機,為了減少重複勞動,可以先初始化配置好一台虛拟機,再克隆出另外兩台虛拟機(記得要修改IP)。

(1)更新yum源(非必須)

yum update -y           

(2)配置網絡

cd /etc/sysconfig/network-scripts/  # 進入網絡配置目錄
vim ifcfg-ens36      # 編輯對應網卡的配置檔案,我的環境是ens36
# 修改網卡配置檔案内容如下所示
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static  # BOOTPROTO的值由dhcp改為static,設為靜态IP
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens36
DEVICE=ens36
ONBOOT=yes          # ONBOOT的值由no改為yes
IPADDR=10.10.10.128
NETMASK=255.255.255.0
GATEWAY=10.10.10.2    # 設定網關,就可以過NAT形式上外網
DNS1=10.10.10.2
ZONE=public
PREFIX=24


service network restart # 重新開機網絡服務使新配置生效           

(3)修改主機名

hostnamectl set-hostname k8s-master # 修改主機名,重新打開終端即可看到主機名已修改成功


# 采取類似方法修改兩台worker節點的主機名
hostnamectl set-hostname k8s-worker1  # 修改10.10.10.131的主機名
hostnamectl set-hostname k8s-worker2  # 修改10.10.10.132的主機名           

(4)配置hosts

vim /etc/hosts
# 添加以下3行
10.10.10.128 k8s-master
10.10.10.131 k8s-worker1
10.10.10.132 k8s-worker2           

(5)關閉主機防火牆

systemctl stop firewalld  # 關閉防火牆
systemctl disable firewalld # 禁用開機自啟動           

(6)關閉selinux

[root@localhost ~]# getenforce   # 檢視selinux狀态
Enforcing                      # selinux未關閉
[root@localhost ~]# setenforce 0  # 臨時關閉selinux
[root@localhost ~]# getenforce   # 檢視selinux狀态
Permissive                     # selinux已關閉


#永久關閉selinux的方法
vim /etc/sysconfig/selinux
将SELINUX=enforcing 替換為SELINUX=disabled,需重新開機主機           

(7)關閉swap

# 臨時關閉
swapoff -a     


# 永久關閉swap
vim /etc/fstab
注釋掉最後一行關于swap的配置           

(8)将橋接的IPv4流量傳遞到iptables的鍊

touch /etc/sysctl.d/k8s.conf  # k8s.conf檔案原來不存在,需要建立
vim /etc/sysctl.d/k8s.conf
# 添加下面4行
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward=1
vm.swappiness=0


sysctl --system               # 加載系統參數,使配置生效           

(9)安裝docker

rpm -qa | grep docker  # 檢視是否已安裝docker元件
yum remove docker docker-common docker-client # 如已安裝,則解除安裝舊版docker相關元件
yum install -y yum-utils    #安裝yum-utils,提供yum-config-manager指令              
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo  #添加阿裡雲的yum源,便于快速下載下傳docker
yum list docker-ce --showduplicates | sort -r   #檢視可擷取的docker版本
yum install -y docker-ce-19.03.5 docker-ce-cli-19.03.5 containerd.io # 安裝指定版本的docker,這裡選擇19.03.5


systemctl enable docker     # 設定開機自啟動
systemctl start docker       # 啟動docker服務
systemctl status docker      # 檢視docker服務狀态           

(10)安裝k8s

添加阿裡雲yum源,便于快速下載下傳k8s

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

下載下傳指定版本的k8s元件

#檢視可擷取的k8s元件版本
yum list kubelet --showduplicates | sort -r


# 這裡選擇安裝1.20.15版本的k8s元件
yum install -y kubelet-1.20.15 kubeadm-1.20.15 kubectl-1.20.15            

啟動服務

systemctl enable kubelet   # 設定開機自啟動
systemctl start kubelet    # 啟動kubelet服務
systemctl status kubelet   # 檢視kubelet服務狀态           

4. Master節點配置

(1)初始化 k8s

執行初始化指令:

kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.20.15 \
--apiserver-advertise-address 10.10.10.128 \
--pod-network-cidr=10.244.0.0/16           

參數說明:

--image-repository:指定鏡像源
--kubernetes-version:指定 k8s 版本,要跟上面安裝的保持一緻
--apiserver-advertise-address:指明用 Master 的哪個 interface 與 Cluster 的其他節點通信。如果 Master 有多個 interface,建議明确指定,如果不指定,kubeadm 會自動選擇有預設網關的 interface。
--pod-network-cidr:指定 Pod 網絡的範圍。k8s支援多種網絡方案,而且不同網絡方案對 --pod-network-cidr 有自己的要求,這裡設定為 10.244.0.0/16 是因為将使用 flannel 網絡方案,必須設定成這個 CIDR。           

初始化腳本執行了以下動作:

kubeadm 執行初始化前的檢查。
生成 token 和證書。
生成 KubeConfig 檔案,kubelet 需要這個檔案與 Master 通信。
安裝 Master 元件,會從 goolge 的 Registry 下載下傳元件的 Docker 鏡像,這一步可能會花一些時間,主要取決于網絡品質。
安裝附加元件 kube-proxy 和 kube-dns。
k8s Master 初始化成功。
提示如何配置 kubectl。
提示如何安裝 Pod 網絡。
提示如何注冊其他節點到 Cluster。           

初始化腳本執行成功的結果:

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


Alternatively, if you are the root user, you can run:


  export KUBECONFIG=/etc/kubernetes/admin.conf


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 10.10.10.128:6443 --token olw0rl.dx8iq0av6yld4npr \
    --discovery-token-ca-cert-hash sha256:9a4a7aa30ea54665d914b86faed89b588fff9937e36d0f28414676c57473702f           

(2)配置kubectl

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

(3)安裝Pod網絡

k8s cluster 工作必須安裝pod網絡,否則pod之間無法通信,k8s支援多種方案,這裡選擇flannel。

由于https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml被牆無法通路,
是以不能采用以下指令線上安裝:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml           

從網上下載下傳kube-flannel.yml檔案:

---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: psp.flannel.unprivileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
    seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
    apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
    apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
  privileged: false
  volumes:
  - configMap
  - secret
  - emptyDir
  - hostPath
  allowedHostPaths:
  - pathPrefix: "/etc/cni/net.d"
  - pathPrefix: "/etc/kube-flannel"
  - pathPrefix: "/run/flannel"
  readOnlyRootFilesystem: false
  # Users and groups
  runAsUser:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  # Privilege Escalation
  allowPrivilegeEscalation: false
  defaultAllowPrivilegeEscalation: false
  # Capabilities
  allowedCapabilities: ['NET_ADMIN', 'NET_RAW']
  defaultAddCapabilities: []
  requiredDropCapabilities: []
  # Host namespaces
  hostPID: false
  hostIPC: false
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  # SELinux
  seLinux:
    # SELinux is unused in CaaSP
    rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
rules:
- apiGroups: ['extensions']
  resources: ['podsecuritypolicies']
  verbs: ['use']
  resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: flannel
  namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
      hostNetwork: true
      priorityClassName: system-node-critical
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni-plugin
        image: rancher/mirrored-flannelcni-flannel-cni-plugin:v1.2
        command:
        - cp
        args:
        - -f
        - /flannel
        - /opt/cni/bin/flannel
        volumeMounts:
        - name: cni-plugin
          mountPath: /opt/cni/bin
      - name: install-cni
        image: quay.io/coreos/flannel:v0.15.1
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.15.1
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN", "NET_RAW"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
      - name: run
        hostPath:
          path: /run/flannel
      - name: cni-plugin
        hostPath:
          path: /opt/cni/bin
      - name: cni
        hostPath:
          path: /etc/cni/net.d
      - name: flannel-cfg
        configMap:
          name: kube-flannel-cfg           

安裝flannel

[root@k8s-master ~]# kubectl apply -f kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel createdconfigmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created           

檢視 pod 狀态,狀态都為Running表示安裝成功

[root@k8s-master 桌面]# kubectl get pod --all-namespaces -o wide
NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE    IP             NODE         NOMINATED NODE   READINESS GATES
kube-system   coredns-7f89b7bc75-kqhd6             1/1     Running   0          68m    10.244.0.3     k8s-master             
kube-system   coredns-7f89b7bc75-vbqqr             1/1     Running   0          68m    10.244.0.2     k8s-master             
kube-system   etcd-k8s-master                      1/1     Running   0          68m    10.10.10.128   k8s-master             
kube-system   kube-apiserver-k8s-master            1/1     Running   0          68m    10.10.10.128   k8s-master             
kube-system   kube-controller-manager-k8s-master   1/1     Running   0          68m    10.10.10.128   k8s-master             
kube-system   kube-flannel-ds-wrhqc                1/1     Running   0          6m3s   10.10.10.128   k8s-master             
kube-system   kube-proxy-gx9nj                     1/1     Running   0          68m    10.10.10.128   k8s-master             
kube-system   kube-scheduler-k8s-master            1/1     Running   0          68m    10.10.10.128   k8s-master           

檢視 node,狀态已為 Ready

[root@k8s-master 桌面]# kubectl get nodes
NAME         STATUS   ROLES                  AGE   VERSION
k8s-master   Ready    control-plane,master   73m   v1.20.15           

5. Worker節點配置

(1)添加 k8s-worker1 和 k8s-worker2

在 k8s-worker1 和 k8s-worker2 上分别執行如下指令,将其注冊到 Cluster 中:

kubeadm join 10.10.10.128:6443 --token olw0rl.dx8iq0av6yld4npr \
    --discovery-token-ca-cert-hash sha256:9a4a7aa30ea54665d914b86faed89b588fff9937e36d0f28414676c57473702f           

這裡的 --token 和--discovery-token-ca-cert-hash 來自前面 kubeadm init 輸出的第 ⑨ 步提示,如果當時沒有記錄下來可以通過 kubeadm token list 檢視。

(2)在k8s-master上檢視worker節點情況

檢視節點運作情況,Ready表明節點加入成功。

[root@k8s-master ~]# kubectl get nodes
NAME                    STATUS   ROLES                  AGE     VERSION
k8s-master              Ready    control-plane,master   84m     v1.20.15
k8s-worker1             Ready                           6m28s   v1.20.15
k8s-worker2             Ready                           6m2s    v1.20.15           

檢視Pod運作情況,Running表示運作正常。

[root@k8s-master ~]# kubectl get pod --all-namespaces
NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE
kube-system   coredns-7f89b7bc75-kqhd6             1/1     Running   1          101m
kube-system   coredns-7f89b7bc75-vbqqr             1/1     Running   1          101m
kube-system   etcd-k8s-master                      1/1     Running   1          101m
kube-system   kube-apiserver-k8s-master            1/1     Running   1          101m
kube-system   kube-controller-manager-k8s-master   1/1     Running   1          101m
kube-system   kube-flannel-ds-9vglr                1/1     Running   1          24m
kube-system   kube-flannel-ds-wrhqc                1/1     Running   1          39m
kube-system   kube-flannel-ds-xz82j                1/1     Running   0          2m51s
kube-system   kube-proxy-fmc9v                     1/1     Running   1          24m
kube-system   kube-proxy-gx9nj                     1/1     Running   1          101m
kube-system   kube-proxy-zrhzt                     1/1     Running   0          2m51s
kube-system   kube-scheduler-k8s-master            1/1     Running   1          101m           

(3)删除和重新添加節點

# 删除 k8s-worker2 節點
[root@k8s-master ~]# kubectl delete node k8s-worker2 


# 重置k8s-worker2 節點
[root@k8s-worker2 ~]# kubeadm reset 


# 将k8s-worker2重新加入叢集
[root@k8s-worker2 ~]# kubeadm join 10.10.10.128:6443 --token olw0rl.dx8iq0av6yld4npr \
    --discovery-token-ca-cert-hash sha256:9a4a7aa30ea54665d914b86faed89b588fff9937e36d0f28414676c57473702f           

6. 使用k8s部署應用

至此k8s叢集已配置完畢,接下來就來部署一個nginx應用感受一下吧。

(1)k8s 支援兩種方式建立資源

方式一:基于指令。

用 kubectl 指令直接建立,在指令行中通過參數指定資源的屬性,比如:

kubectl run nginx-deployment --image=nginx:1.23.2 --replicas=2           

方式二:基于配置檔案。

通過YAML配置檔案和 kubectl apply 指令建立,比如:

kubectl apply -f nginx.yml           

兩種方式比較:

基于指令:
簡單直覺快捷,上手快。
适合臨時測試或實驗。


基于配置檔案:
配置檔案描述了 What,即應用最終要達到的狀态。
配置檔案提供了建立資源的模闆,能夠重複部署。
可以像管理代碼一樣管理部署。
适合正式的、跨環境的、規模化部署。
要求熟悉配置檔案的文法,有一定難度。           

(2)采用 Deployment 部署應用

k8s通過Controller來管理Pod的生命周期。為了滿足不同業務場景,k8s開發了Deployment、ReplicaSet、DaemonSet、StatefulSet、Job等多種Controller。這次采用最常用的Deployment,對應的 nginx.yml 内容為:

apiVersion: apps/v1
kind: Deployment
metadata:
   name: nginx-deployment
   labels:
     app: nginx-deployment
spec:
   replicas: 3
   selector:
      matchLabels:
         app: nginx-pod
   template:
      metadata:
         labels:
            app: nginx-pod
      spec:
         containers:
         - name: nginx
           image: nginx:1.23.2
           imagePullPolicy: IfNotPresent
           ports:
           - containerPort: 80           

參數說明:

apiVersion 是目前配置格式的版本。
kind 是要建立的資源類型,這裡是 Deployment。
metadata 是該資源的中繼資料,name 是必需的中繼資料項。
spec 部分是該 Deployment 的規格說明。
replicas 指明副本數量,預設為 1。
template 定義 Pod 的模闆,這是配置檔案的重要部分。
metadata 定義 Pod 的中繼資料,至少要定義一個 label。label 的 key 和 value 可以任意指定。
spec 描述 Pod 的規格,此部分定義 Pod 中每一個容器的屬性,name 和 image 是必需的。           

執行指令,開始部署應用

[root@k8s-master 桌面]# kubectl apply -f nginx.yml
deployment.apps/nginx-deployment created           

檢視應用部署情況,還在進行中...

[root@k8s-master 桌面]# kubectl get deployment nginx-deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   0/3     3            0           23s
[root@k8s-master 桌面]# kubectl get pods
NAME                                READY   STATUS              RESTARTS   AGE
nginx-deployment-84f787d66f-jvtwj   0/1     ContainerCreating   0          37s
nginx-deployment-84f787d66f-sjsqj   0/1     ContainerCreating   0          37s
nginx-deployment-84f787d66f-x5mjp   0/1     ContainerCreating   0          37s           

檢視某個pod的部署狀态詳情

[root@k8s-master 桌面]# kubectl describe pod nginx-deployment-84f787d66f-x5mjp
[...省略...]
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  2m25s  default-scheduler  Successfully assigned default/nginx-deployment-84f787d66f-jvtwj to k8s-worker1
  Normal  Pulling    2m24s  kubelet            Pulling image "nginx:1.23.2"
  Normal  Pulled     83s    kubelet            Successfully pulled image "nginx:1.23.2" in 1m1.152513339s
  Normal  Created    82s    kubelet            Created container nginx
  Normal  Started    82s    kubelet            Started container nginx           

已完成部署

[root@k8s-master 桌面]# kubectl get deployment nginx-deployment -o wide
NAME               READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
nginx-deployment   3/3     3            3           13m   nginx        nginx:1.23.2   app=nginx-pod           

已生成3個副本,其中一個跑着worker1節點上,2個跑在worker2節點上。

[root@k8s-master 桌面]# kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
nginx-deployment-84f787d66f-jvtwj   1/1     Running   0          15m   10.244.1.2   k8s-worker1             
nginx-deployment-84f787d66f-sjsqj   1/1     Running   0          15m   10.244.2.3   k8s-worker2             
nginx-deployment-84f787d66f-x5mjp   1/1     Running   0          15m   10.244.2.2   k8s-worker2           

可以正常通路應用,通路方式是 pod ip + port

[root@k8s-master 桌面]# curl http://10.244.2.2:80
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }


Welcome to nginx!


If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.


For online documentation and support please refer to
nginx.org.


Commercial support is available at
nginx.com.
Thank you for using nginx.           

至此,k8s叢集搭建工作告一段落,有關k8s的其他知識,留待以後再跟大家分享。

7. 後記

雖然網上有很多資料可以參考,但實踐的過程還是蠻曲折的,知易行難,所幸在解決了各種奇奇怪怪的報錯後最終完成任務。由于還處在入門階段,這次是基于前人軌迹亦步亦趨走下來的,沒有太多自己的思考,比如關閉防火牆、關閉selinux這種事,也不應該是搞安全的人幹出來的,但為了poc能夠順利通過,還是在沒有深究原因的情況下很“違心”地做了。

目前k8s最新版已到1.25,其中 1.24是個分水嶺,k8s從這個版本開始正式棄用了dockershim中轉模式,而是直接調用containerd,“沒有了中間商賺差價”可以明顯提升性能效率,算是重大更新了,有興趣的讀者可以移步《【k8s】Kubernetes“棄用Docker”是怎麼回事?》(連結見參考文獻)做進一步了解。不過,在“穩定壓倒一切”的指導方針下,估計國内吃螃蟹的企業暫時不會太多,可能是不夠痛不差錢亦或是極客精神的缺失吧。

靜下心來思考k8s的設計理念,不禁感慨老外确實厲害——簡潔高效、舉止優雅,“增之一分則太長,減之一分則太短 ;著粉則太白,施朱則太赤”,各個元件分工明确、環環相扣,像一台精密儀器,更像一件藝術品,再貼上免費、開源的标簽,再次印證了谷歌是一家有能力、有格局的偉大公司。我在想,假如我們能在文字的遣詞造句、對仗排比上省點精力,也許能在技術的精益求精、開拓創新方面更有建樹吧。畢竟,文山會海是将軍的地獄,金戈鐵馬才是戰士的天堂。

8. 參考文獻

1、《每天5分鐘玩轉 Docker 容器技術》,CloudMan著,清華大學出版社

2、《每天5分鐘玩轉 Kubernetes》,CloudMan著,清華大學出版社

3、《【k8s】Kubernetes“棄用Docker”是怎麼回事?》:

https://www.jianshu.com/p/71ad22345cc5

繼續閱讀