日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Kubernetes 號稱云原生操作系統,可想而知其復雜程度也是非常大的,由許多組件組成,我們很難去追蹤到所有的組件信息。

構建最小化的 Kubernetes 集群

 

上圖中至少列出了七八個組件,我們這里會忽略其中大部分組件,要運行一個最小級別的 Kubernetes 至少要包括如下三個基本組件:

  • kubelet:在集群中每個節點上運行的代理,負責容器真正運行的核心組件
  • kube-apiserver:Kubernetes 控制平面的組件,提供資源操作的唯一入口
  • 容器運行時(Docker)

這里我們來嘗試配置一個最小級別的 Kubernetes,這對于我們加速對集群的理解也是非常有幫助的。

安裝

首先需要在節點上安裝 Docker 容器運行時,我們這里使用的是操作系統為 centos7 版本,在 root 用戶下面執行相關操作。執行如下所示命令直接安裝即可:

$ yum install -y yum-utils
$ yum-config-manager 
    --add-repo 
    https://download.docker.com/linux/centos/docker-ce.repo
$ yum install -y docker-ce docker-ce-cli containerd.io
$ systemctl enable docker
$ systemctl daemon-reload
$ systemctl start docker

接下來,我們需要獲取 Kubernetes 二進制文件。實際上,我們只需要使用 kubelet 組件來引導我們的“集群”,因為我們可以使用 kubelet 來運行其他組件,一旦集群啟動了,我們就可以使用 kubectl 來進行操作了。

$ curl -L https://dl.k8s.io/v1.18.5/kubernetes-server-linux-amd64.tar.gz > server.tar.gz
$ tar xzvf server.tar.gz
$ cp kubernetes/server/bin/kubelet .
$ cp kubernetes/server/bin/kubectl .
$ ./kubelet --version
Kubernetes v1.18.5

由于 kubelet 配置太多,但是這里我們只需要幾個設置參數即可:

$ ./kubelet -h
<far too much output to copy here>
$ ./kubelet -h | wc -l
284

我們這里需要使用的是 --pod-manifest-path 這個參數,該參數用于指定要運行的靜態 Pod 文件的目錄,靜態 Pod 不受 Kubernetes API 管理,雖然平時我們在使用 Kubernetes 的時候比較少使用靜態 Pod,但是對于引導集群卻是非常有用,對 Kubeadm 熟悉的應該知道,該方案就是利用靜態 Pod 將 Kubernetes 控制面板容器化的。下面我們來嘗試下是否可以使用 kubelet 來運行 Pod。

首先我們創建一個靜態 Pod 目錄來運行 kubelet:

$ mkdir pods
$ ./kubelet --pod-manifest-path=pods

然后重新打開一個終端,創建如下所示的 Pod 資源清單文件:

$ cat <<EOF > pods/hello.yaml
apiVersion: v1
kind: Pod
metadata:
  name: hello
spec:
  containers:
  - image: busybox
    name: hello
    command: ["echo", "hello world!"]
EOF

上面資源清單出現在 pods 目錄后,就可以在 kubelet 日志中看到如下所示的錯誤信息:

......
E0707 10:25:58.489839   21311 pod_workers.go:191] Error syncing pod ab61ef0307c6e0dee2ab05dc1ff94812 ("hello-iz2ze8x2keg0a301rpa7cvz_default(ab61ef0307c6e0dee2ab05dc1ff94812)"), skipping: failed to "CreatePodSandbox" for "hello-iz2ze8x2keg0a301rpa7cvz_default(ab61ef0307c6e0dee2ab05dc1ff94812)" with CreatePodSandboxError: "CreatePodSandbox for pod "hello-iz2ze8x2keg0a301rpa7cvz_default(ab61ef0307c6e0dee2ab05dc1ff94812)" failed: rpc error: code = Unknown desc = failed pulling image "k8s.gcr.io/pause:3.2": Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)"
......

這是因為 Kubernetes 的 Pod 默認情況下會優先啟動一個 k8s.gcr.io/pause:3.2的 pause 鏡像,而該鏡像由于某些原因獲取不到,我們可以 --pod-infra-container-image 參數重新指定一個可以訪問到的鏡像:

$ ./kubelet --pod-manifest-path=pods --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.2

現在我們檢查下 Docker 容器是否有新的容器啟動:

$ docker ps -a
CONTAINER ID        IMAGE                  COMMAND                 CREATED             STATUS                      PORTS               NAMES
d6e822dbcebd        busybox                                                              "echo 'hello world!'"    27 seconds ago      Exited (0) 26 seconds ago                             k8s_hello_hello-iz2ze8x2keg0a301rpa7cvz_default_ab61ef0307c6e0dee2ab05dc1ff94812_3
102b999be2dd        registry.aliyuncs.com/google_containers/pause:3.2                    "/pause"                 2 minutes ago       Up 2 minutes                                          k8s_POD_hello-iz2ze8x2keg0a301rpa7cvz_default_ab61ef0307c6e0dee2ab05dc1ff94812_0
$ docker logs k8s_hello_hello-iz2ze8x2keg0a301rpa7cvz_default_ab61ef0307c6e0dee2ab05dc1ff94812_3
hello world!

kubelet 通過我們指定的靜態 Pod 目錄,讀取其中的 YAML 文件來創建 Pod。由于我們這里執行的就是 echo 命令,所以會不斷的重啟,驗證完成后刪除該 YAML 文件即可。

當然這還不夠,我們還需要運行 APIServer,要做到這一點,我們需要首先運行 etcd,同樣的我們也可以使用靜態 Pod 來運行 etcd,創建如下所示的 etcd 資源清單文件:

$ cat <<EOF > pods/etcd.yaml
apiVersion: v1
kind: Pod
metadata:
  name: etcd
  namespace: kube-system
spec:
  containers:
  - name: etcd
    command:
    - etcd
    - --data-dir=/var/lib/etcd
    image: registry.aliyuncs.com/google_containers/etcd:3.4.3-0
    volumeMounts:
    - mountPath: /var/lib/etcd
      name: etcd-data
  hostNetwork: true
  volumes:
  - hostPath:
      path: /var/lib/etcd
      type: DirectoryOrCreate
    name: etcd-data
EOF

這就是一個非常普通的 Pod 資源清單文件,大家應該都非常熟悉,不過還是需要注意兩件事:

  • 我們將宿主機的 /var/lib/etcd 目錄掛載到 Pod 容器中,這樣可以保證 etcd 在重新啟動以后數據依然存在。
  • 另外我們設置了 hostNetwork=true,這樣可以使容器和宿主機共享網絡命名空間,可以讓 APIServer 更容易和 etcd 通信。

我們可以使用如下所示的命令來檢查 etcd 是否啟動成功:

$ curl localhost:2379/version
{"etcdserver":"3.4.3","etcdcluster":"3.4.0"}
$ tree /var/lib/etcd/
/var/lib/etcd/
└── member
    ├── snap
    │   └── db
    └── wal
        ├── 0000000000000000-0000000000000000.wal
        └── 0.tmp

3 directories, 3 files

現在 etcd 啟動成功了,就可以來啟動 APIServer 了,我們這里只需要通過參數 --etcd-servers 傳遞 etcd 地址即可,同樣在靜態 pods 目錄下面創建如下所示的資源清單:

$ cat <<EOF > pods/apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - name: kube-apiserver
    command:
    - kube-apiserver
    - --etcd-servers=http://127.0.0.1:2379
    image: cnych/kube-apiserver:v1.18.5  # 阿里云鏡像未同步
  hostNetwork: true
EOF

創建完成后正常 APIServer 就會正常啟動,可以通過如下所示的命令來驗證:

$ curl localhost:8080/healthz
ok
$ curl localhost:8080/api/v1/pods
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/pods",
    "resourceVersion": "59"
  },
  "items": []
}

而且 kubectl 也不需要額外的配置就可以直接使用了:

$ ./kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
$ ./kubectl get pod
No resources found in default namespace.

這是因為 kubectl 默認是通過 localhost:8080 和 APIServer 進行通信的。

配置

但是當我們去獲取剛剛創建的靜態 Pod 的時候卻發現沒有對應的記錄:

$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.

而且運行 kubelet 的節點也根本沒有顯示:

$ ./kubectl get nodes
No resources found in default namespace.

這其實是因為 kubelet 不知道如何與 APIServer 進行通信并更新狀態造成的,我們可以通過 kubelet 的 --kubeconfig 參數來指定 KUBECONFIG 文件的路徑,可以通過該文件來指定如何連接到 APIServer。由于我們這里就是啟動一個最新的 Kubernetes,沒有身份驗證或者證書之類的麻煩事情,所以非常簡單,創建名為 kubeconfig.yaml 的如下所示文件:

apiVersion: v1
kind: Config
clusters:
- cluster:
    server: http://127.0.0.1:8080
  name: mink8s
contexts:
- context:
    cluster: mink8s
  name: mink8s
current-context: mink8s

然后殺掉 kubelet 進程,添加上 --kubeconfig 參數重新運行:

$ ./kubelet --pod-manifest-path=pods --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.2 --kubeconfig=kubeconfig.yaml

隔一會兒后我們再次使用 kubectl 來查看上面我們運行的靜態 Pod 就正常了:

$ ./kubectl get pods -A
NAMESPACE     NAME                    READY   STATUS             RESTARTS   AGE
default       hello-mink8s            0/1     CrashLoopBackOff   261        21h
kube-system   etcd-mink8s             1/1     Running            0          21h
kube-system   kube-apiserver-mink8s   1/1     Running            0          21h
$ ./kubectl get nodes -owide
NAME     STATUS   ROLES    AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION       CONTAINER-RUNTIME
mink8s   Ready    <none>   21h   v1.18.5   10.70.10.228   <none>        CentOS Linux 7 (Core)   4.15.0-109-generic   docker://19.3.6

這樣我們就運行了一個最小功能集的 Kubernetes 集群了。下面我們來嘗試運行一個普通的 Pod 看能否正常運行。

同樣嘗試來創建一個 Nginx 的 Pod:

$ cat <<EOF > nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
EOF

然后使用 kubectl 來創建上面的資源對象:

$ ./kubectl Apply -f nginx.yaml
Error from server (Forbidden): error when creating "nginx.yaml": pods "nginx" is
forbidden: error looking up service account default/default: serviceaccount
"default" not found
$ ./kubectl get serviceaccounts
No resources found in default namespace.

可以看到有錯誤信息,這是因為我們上面部署的最小級別的 Kubernetes 環境完整性還是不夠,沒有自動生成默認的 default 這個 ServiceAccount,我們來手動創建再來驗證一次:

$ cat <<EOF | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
EOF
serviceaccount/default created
$ ./kubectl apply -f nginx.yaml
Error from server (ServerTimeout): error when creating "nginx.yaml": No API
token found for service account "default", retry after the token is
automatically created and added to the service account

我們手動創建了 ServiceAccount,但是卻并沒有創建對應的身份驗證的 Token,我們可以看到以前很多自動完成的操作現在都沒有了。

不過我們可以通過 automountServiceAccountToken 參數在 ServiceAccount 上來規避這個特定問題,因為實際上我們這里并不需要使用 ServiceAccount:

$ cat <<EOF | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
automountServiceAccountToken: false
EOF
serviceaccount/default configured
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   0/1     Pending   0          13m

現在我們可以看到 Pod 出現了,但是處于 pending 狀態,這是因為我們并沒有部署 kube-scheduler 這個負責調度的組件,自然是不能被調度的,當然我們也可以不需要調度程序,直接使用 nodeName 屬性將 Pod 手動固定到節點上即可:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
  nodeName: mink8s

現在將之前部署的 Pod 刪除重新來部署,正常就可以運行了:

$ ./kubectl delete pod nginx
pod "nginx" deleted
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods -owide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          30s   172.17.0.2   mink8s   <none>           <none>
$ curl -s 172.17.0.2 | head -4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

為了驗證 Pod 與 Pod 之間是可以正常通信的,我們可以使用如下的 Pod 來驗證:

$ cat <<EOF | ./kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: curl
spec:
  containers:
  - image: curlimages/curl
    name: curl
    command: ["curl", "172.17.0.2"]
  nodeName: mink8s
EOF
pod/curl created
$ ./kubectl logs curl | head -6
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

可以看到可以正常通信。這樣我們就完成了一個最小的 Kubernetes 集群部署。當然這也僅僅是為了簡化我們對 Kubernetes 的理解而已,在實際的生產環境是絕對不能這樣去部署使用的。

參考

  • https://eevans.co/blog/minimum-viable-kubernetes/
  • https://commons.wikimedia.org/w/index.php?curid=53571935
  • https://kubernetes.io/docs/concepts/overview/components/
  • https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/

分享到:
標簽:集群 Kubernetes
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定