default account,load default什么意思

  

  Kubernetes被称为云原生操作系统。可想而知,它的复杂性也是非常大的。它由许多组件组成,我们很难追踪所有的组件信息。   

  

     

  

  上图至少列出了七八个组件,这里大部分我们就忽略了。要运行最低级别的Kubernetes,您必须至少包括以下三个基本组件:   

  

  Kubelet:运行在集群中每个节点上的代理,负责容器真实操作的核心组件Kube-API server: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-clicontainered . io $ system CTL enable decker $ system CTL daemon-reload $ system CTL 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/kube let。$ CP Kubernetes/server/bin/kubectl。$./Kubelet-version kubernetes v 1 . 18 . 5由于kube let的配置太多,这里我们只需要几个设置参数:   

  

  $./kubelet-hfar输出太多,无法复制到此处$。/kubelet-h | WC-L284这里需要用到的是参数-pod - pod-manifest-path,用来指定要运行的静态Pod文件的目录,静态Pod不是由Kubernetes API管理的。虽然我们在使用Kubernetes时很少使用static Pod,但是它对于引导集群非常有用。熟悉Kubeadm的人应该知道,这个方案使用静态Pod来容器化Kubernetes控制面板。我们试试看能不能用kubelet来运行Pod。   

  

  首先,我们创建一个静态Pod目录来运行kubelet:   

  

  $ mkdir Pods $。/kube let-pod-manifest-path=pods然后重新打开一个终端并创建一个pod资源清单文件,如下所示:   

  

  $ cat EOF pods/hello . yamlapiversion : v1 kind : podmetadata : name : hello spec : containers :-image : busybox name : hello command : ' echo ',' hello world!'在pods目录中出现EOF上面的资源列表后,您可以在kubelet日志中看到以下错误消息:   

  

  .e 0707 10:25:58.489839 21311 pod _ workers . go :191同步pod ab 61 ef 0307 c 6 e 0 dee 2 ab 05 DC 1 ff 94812时出错(' hello-iz 2 ze 8 x2 keg 0 a 301 RPA 7 cvz _ def故障(ab 61 ef 0307 c 6 e 0 dee 2 ab 05 DC 1 ff 94812)'),skipping:未能   

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 -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESd6e822dbcebd busybox "echo 'hello world!'" 27 seconds ago Exited (0) 26 seconds ago k8s_hello_hello-iz2ze8x2keg0a301rpa7cvz_default_ab61ef0307c6e0dee2ab05dc1ff94812_3102b999be2dd 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_3hello world!kubelet 通过我们指定的静态 Pod 目录,读取其中的 YAML 文件来创建 Pod。由于我们这里执行的就是 echo 命令,所以会不断的重启,验证完成后删除该 YAML 文件即可。

  

当然这还不够,我们还需要运行 APIServer,要做到这一点,我们需要首先运行 etcd,同样的我们也可以使用静态 Pod 来运行 etcd,创建如下所示的 etcd 资源清单文件:

  

$ cat <<EOF > pods/etcd.yamlapiVersion: v1kind: Podmetadata: name: etcd namespace: kube-systemspec: 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-dataEOF这就是一个非常普通的 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.tmp3 directories, 3 files现在 etcd 启动成功了,就可以来启动 APIServer 了,我们这里只需要通过参数 --etcd-servers 传递 etcd 地址即可,同样在静态 pods 目录下面创建如下所示的资源清单:

  

$ cat <<EOF > pods/apiserver.yamlapiVersion: v1kind: Podmetadata: name: kube-apiserver namespace: kube-systemspec: containers: - name: kube-apiserver command: - kube-apiserver - --etcd-servers=http://127.0.0.1:2379 image: cnych/kube-apiserver:v1.18.5 # 阿里云镜像未同步 hostNetwork: trueEOF创建完成后正常 APIServer 就会正常启动,可以通过如下所示的命令来验证:

  

$ curl localhost:8080/healthzok$ curl localhost:8080/api/v1/pods{ "kind": "PodList", "apiVersion": "v1", "metadata": { "selfLink": "/api/v1/pods", "resourceVersion": "59" }, "items": <>}而且 kubectl 也不需要额外的配置就可以直接使用了:

  

$ ./kubectl versionClient 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 podNo resources found in default namespace.这是因为 kubectl 默认是通过 localhost:8080 和 APIServer 进行通信的。

  

配置但是当我们去获取刚刚创建的静态 Pod 的时候却发现没有对应的记录:

  

$ ./kubectl get pod -n kube-systemNo resources found in kube-system namespace.而且运行 kubelet 的节点也根本没有显示:

  

$ ./kubectl get nodesNo resources found in default namespace.这其实是因为 kubelet 不知道如何与 APIServer 进行通信并更新状态造成的,我们可以通过 kubelet 的 --kubeconfig 参数来指定 KUBECONFIG 文件的路径,可以通过该文件来指定如何连接到 APIServer。由于我们这里就是启动一个最新的 Kubernetes,没有身份验证或者证书之类的麻烦事情,所以非常简单,创建名为 kubeconfig.yaml 的如下所示文件:

  

apiVersion: v1kind: Configclusters:- cluster: server: http://127.0.0.1:8080 name: mink8scontexts:- context: cluster: mink8s name: mink8scurrent-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 -ANAMESPACE NAME READY STATUS RESTARTS AGEdefault hello-mink8s 0/1 CrashLoopBackOff 261 21hkube-system etcd-mink8s 1/1 Running 0 21hkube-system kube-apiserver-mink8s 1/1 Running 0 21h$ ./kubectl get nodes -owideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIMEmink8s 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.yamlapiVersion: v1kind: Podmetadata: name: nginxspec: containers: - image: nginx name: nginxEOF然后使用 kubectl 来创建上面的资源对象:

  

$ ./kubectl apply -f nginx.yamlError from server (Forbidden): error when creating "nginx.yaml": pods "nginx" isforbidden: error looking up service account default/default: serviceaccount"default" not found$ ./kubectl get serviceaccountsNo resources found in default namespace.可以看到有错误信息,这是因为我们上面部署的最小级别的 Kubernetes 环境完整性还是不够,没有自动生成默认的 default 这个 ServiceAccount,我们来手动创建再来验证一次:

  

$ cat <<EOF | ./kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata: name: default namespace: defaultEOFserviceaccount/default created$ ./kubectl apply -f nginx.yamlError from server (ServerTimeout): error when creating "nginx.yaml": No APItoken found for service account "default", retry after the token isautomatically created and added to the service account我们手动创建了 ServiceAccount,但是却并没有创建对应的身份验证的 Token,我们可以看到以前很多自动完成的操作现在都没有了。

  

不过我们可以通过 automountServiceAccountToken 参数在 ServiceAccount 上来规避这个特定问题,因为实际上我们这里并不需要使用 ServiceAccount:

  

$ cat <<EOF | ./kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata: name: default namespace: defaultautomountServiceAccountToken: falseEOFserviceaccount/default configured$ ./kubectl apply -f nginx.yamlpod/nginx created$ ./kubectl get podsNAME READY STATUS RESTARTS AGEnginx 0/1 Pending 0 13m现在我们可以看到 Pod 出现了,但是处于 pending 状态,这是因为我们并没有部署 kube-scheduler 这个负责调度的组件,自然是不能被调度的,当然我们也可以不需要调度程序,直接使用 nodeName 属性将 Pod 手动固定到节点上即可:

  

apiVersion: v1kind: Podmetadata: name: nginxspec: containers: - image: nginx name: nginx nodeName: mink8s现在将之前部署的 Pod 删除重新来部署,正常就可以运行了:

  

$ ./kubectl delete pod nginxpod "nginx" deleted$ ./kubectl apply -f nginx.yamlpod/nginx created$ ./kubectl get pods -owideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESnginx 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: v1kind: Podmetadata: name: curlspec: containers: - image: curlimages/curl name: curl command: <"curl", "172.17.0.2"> nodeName: mink8sEOFpod/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=53571935https://kubernetes.io/docs/concepts/overview/components/https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/

相关文章