构建最小化的 Kubernetes 集群( 二 )


$ cat <<EOF > pods/etcd.yamlapiVersion: v1kind: Podmetadata:name: etcdnamespace: kube-systemspec:containers:- name: etcdcommand:- etcd- --data-dir=/var/lib/etcdimage: registry.aliyuncs.com/google_containers/etcd:3.4.3-0volumeMounts:- mountPath: /var/lib/etcdname: etcd-datahostNetwork: truevolumes:- hostPath:path: /var/lib/etcdtype: DirectoryOrCreatename: 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-apiservernamespace: kube-systemspec:containers:- name: kube-apiservercommand:- kube-apiserver- --etcd-servers=http://127.0.0.1:2379image: 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:8080name: mink8scontexts:- context:cluster: mink8sname: 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 -ANAMESPACENAMEREADYSTATUSRESTARTSAGEdefaulthello-mink8s0/1CrashLoopBackOff26121hkube-systemetcd-mink8s1/1Running021hkube-systemkube-apiserver-mink8s1/1Running021h$ ./kubectl get nodes -owideNAMESTATUSROLESAGEVERSIONINTERNAL-IPEXTERNAL-IPOS-IMAGEKERNEL-VERSIONCONTAINER-RUNTIMEmink8sReady<none>21hv1.18.510.70.10.228<none>CentOS Linux 7 (Core)4.15.0-109-genericdocker://19.3.6这样我们就运行了一个最小功能集的 Kubernetes 集群了 。下面我们来尝试运行一个普通的 Pod 看能否正常运行 。
同样尝试来创建一个 Nginx 的 Pod:
$ cat <<EOF > nginx.yamlapiVersion: v1kind: Podmetadata:name: nginxspec:containers:- image: nginxname: nginxEOF


推荐阅读