Kubernetes学习日记(一)

Kubernetes学习日记(一)

暑期加入了沃天宇老师的实验室进行暑期的实习。在正式开始工作之前,师兄先让我了解一下技术栈,需要了解的有docker、k8s、springboot、springcloud。

谨以一系列博客记录一下自己学习的笔记。更多内容见Github

2021/7/7

参考资料

官网:https://kubernetes.io/

因为官方文档支持中文,并且挺全面的,就先不需要别的资料了。

什么是k8s

已经了解了docker这个容器的概念,k8s在官网给出的概念就好理解了:

k8s,全称Kubernetes,是一个用于自动部署、扩展和管理容器化应用程序的开源系统。

如果说docker用来构建、运行容器,那么k8s则用来部署和管理容器。

基本概念

术语表:https://kubernetes.io/zh/docs/reference/glossary/

  • pod:集群上一组正在运行的容器,是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元;
  • node:节点,一台机器;
  • cluster:集群;
  • controller:控制器,通过apiserver监控集群状态、并致力于将当前状态转换成期望状态的组件;
  • service:将运行在pod上的应用暴露为网络服务;
  • volume:卷,类似于docker中的volume,但是提供了更丰富的功能,详见https://kubernetes.io/zh/docs/concepts/storage/volumes/

k8s组件

  • Control Plane Components:控制面板,负责检测和响应集群事件,对整个集群做出全局决策(如在某些条件下启动新的pod);
    • kube-apiserver:控制面板的前端,支持水平扩展(部署多个实例);
    • etcd:一个key-value数据库,作为整个集群的数据的后台数据库;
    • kube-scheduler:为pod分配node的调度器;
    • kube-controller-manager:一系列控制器的整合,支持水平扩展;
      • node controller:节点控制器,节点出现故障时进行通知和响应;
      • job controller:监测代表一次性任务的Job对象,然后创建pod来运行这些任务直至完成;
      • endpoints controller:填充端点(Endpoints)对象,即连接servicepod
      • service account & token controllers:为新的命名空间创建默认帐户和 API 访问令牌;
    • cloud-controller-manager:用于和云服务提供商/云平台交互的控制器的集合,支持水平扩展;
      • node controller:节点控制器,用于在节点终止响应后检查云提供商以确定节点是否已被删除;
      • route controller:路由控制器,用于在云基础架构中设置路由;
      • service controller:服务控制器,用于创建、更新和删除云平台的负载均衡;
  • Node Components:节点组件,在节点上运行的组件,维护pod并提供k8s运行环境;
    • kubelet:在节点上运行的代理(agent),通过多种方式接收PodSpecs并保证其中描述的容器处于运行状态且健康,只管理由k8s创建的容器;
    • kube-proxy:在节点上运行的网络代理,维护节点上的网络规则,这些规则允许从集群内部或外部的网络会话与pod进行网络通信;
    • container runtime:容器的运行时,k8s支持docker、containerd、CRI-O以及任何Kubernetes CRI的实现;
  • Addons:插件,插件通过使用k8s资源,来实现集群工能;
    • DNS:和环境中其它DNS服务器一起工作,它为k8s服务提供DNS记录;
    • dashboard:仪表盘,是一个基于Web的用户界面,方便进行管理和故障排除;
    • container resource monitoring:容器资源监控,将容器的一些常见的时间序列度量值保存到一个记账的数据库,并提供浏览的页面;
    • cluster-level logging:集群日志,负责将容器的日志数据保存到一个集中的日志存储中,该存储提供搜索和浏览接口;

k8s对象

每个k8s对象有两个嵌套的字段:

  • spec:规约,描述期望状态,创建对象时,由维护人员提供;
  • state:当前状态,有对象实际情况产生;

k8s的OpenAPI要求请求体中包含JSON格式的spec信息,但是我们使用kebectl时,可以通过yaml文件来描述。以下为官方示例:

application/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

其中以下字段是必须的:

  • apiVersion:所使用的k8s API版本;
  • kind:所创建的的对象的类别;
  • metadata: 帮助唯一性标识对象的一些数据,包括一个name字符串、UID和可选的namespace

更多spec内容可以参考Kubernetes API

标识对象

关于唯一地标识对象,有两种途径,一种是通过name,一种是通过UID

UID由k8s管理,保证全局唯一。

而对于name,两个同类对象不能同时拥有一样的name,并且name视情况可能需要满足RFC 1123中的DNS subdomain/DNS label的约束,也可能需要满足路径名约束,总的来说,满足下面4个约束就可以满足绝大部分情况:

  1. 不多于63个字符;
  2. 只能包含小写字母、数字,以及'-';
  3. 须以字母/数字开头;
  4. 须以字母/数字结尾;

当需要的名字过多的时候,我们可以通过命名空间来进行管理。

metadata

除了前面提到的name字符串、UID和可选的namespace,metadata还可以保存更多对象信息。

我们也可以通过标签来进行更细致的条件筛选。k8s中,标签是一种key-value结构,我们可以通过判断某个key对应的value是否符合要求来筛选对象。

官方给出了一些标签的示例:

  • "release":"stable", "release":"canary"
  • "environment":"dev", "environment":"qa", "environment":"production"
  • "tier":"frontend", "tier":"backend", "tier":"cache"
  • "partition":"customerA", "partition":"customerB"
  • "track":"daily", "track":"weekly"

推荐使用的标签如下:https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/common-labels/

而另一种信息是注解。注解也是一种key-value结构,和标签的表现形式很像,但不同于标签,注解不能用于筛选。

官方给出了使用注解的一些场景:

  • 由声明性配置所管理的字段。 将这些字段附加为注解,能够将它们与客户端或服务端设置的默认值、 自动生成的字段以及通过自动调整大小或自动伸缩系统设置的字段区分开来。
  • 构建、发布或镜像信息(如时间戳、发布 ID、Git 分支、PR 数量、镜像哈希、仓库地址)。
  • 指向日志记录、监控、分析或审计仓库的指针。
  • 可用于调试目的的客户端库或工具信息:例如,名称、版本和构建信息。
  • 用户或者工具/系统的来源信息,例如来自其他生态系统组件的相关对象的 URL。
  • 轻量级上线工具的元数据信息:例如,配置或检查点。
  • 负责人员的电话或呼机号码,或指定在何处可以找到该信息的目录条目,如团队网站。
  • 从用户到最终运行的指令,以修改行为或使用非标准功能。

相比于将这些信息保存在数据库或文件中,使用注解可以方便开发人员生成用于部署、管理、自检的客户端共享库和工具。

安装

安装适合用于学习的minikube:https://minikube.sigs.k8s.io/docs/start/

minikube是一个单节点的k8s。

然后安装命令行辅助工具kubectl:https://kubernetes.io/zh/docs/tasks/tools/install-kubectl-windows/

这里下载下来的是一个单体的exe,直接放在一个在PATH中的文件夹里就可以了。

创建集群

创建并运行一个集群:

minikube start

获取集群信息:

kubectl cluster-info

获取节点信息:

kubectl get nodes

结果如下(将路径等无关信息删去了):

PS D:\xxxx\Learning> minikube start
😄  Microsoft Windows 10 Home China 10.0.19041 Build 19041 上的 minikube v1.21.0
✨  根据现有的配置文件使用 docker 驱动程序
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
🏃  Updating the running docker "minikube" container ...
❗  This container is having trouble accessing https://k8s.gcr.io
💡  To pull new external images, you may need to configure a proxy: https://minikube.sigs.k8s.io/docs/reference/networking/proxy/
🐳  正在 Docker 20.10.7 中准备 Kubernetes v1.20.7…
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default    
PS D:\xxxx\Learning> kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:57180
KubeDNS is running at https://127.0.0.1:57180/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
PS D:\xxxx\Learning> kubectl get nodes
NAME       STATUS   ROLES    AGE     VERSION
minikube   Ready    <none>   3m51s   v1.20.7

启动minikube dashboard:

minikube dashboard

然后就可以在浏览器访问dashboard了:

创建Deployment

使用如下命令创建一个Deployment:

kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
  • hello-node是这个deployment的名字;
  • --image指定了创建deployment所使用的镜像;

查看deployment信息:

kubectl get deployments

查看pod信息:

kubectl get pods

查看集群事件:

kubectl get events

查看kubectl配置:

kubectl config view

结果如下:

PS D:\xxxx\Learning> kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
deployment.apps/hello-node created
PS D:\xxxx\Learning> kubectl get deployments
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
hello-node   0/1     1            0           11s
PS D:\xxxx\Learning> kubectl get pods
hello-node-7567d9fdc9-z879j   0/1     ImagePullBackOff   0          2m41s
PS D:\xxxx\Learning> kubectl get events
LAST SEEN   TYPE      REASON                    OBJECT                             MESSAGE
2m59s       Normal    Scheduled                 pod/hello-node-7567d9fdc9-z879j    Successfully assigned default/hello-node-7567d9fdc9-z879j to minikube
38s         Normal    Pulling                   pod/hello-node-7567d9fdc9-z879j    Pulling image "k8s.gcr.io/echoserver:1.4"
23s         Warning   Failed                    pod/hello-node-7567d9fdc9-z879j    Failed to pull image "k8s.gcr.io/echoserver:1.4": rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
23s         Warning   Failed                    pod/hello-node-7567d9fdc9-z879j    Error: ErrImagePull
9s          Normal    BackOff                   pod/hello-node-7567d9fdc9-z879j    Back-off pulling 
image "k8s.gcr.io/echoserver:1.4"
9s          Warning   Failed                    pod/hello-node-7567d9fdc9-z879j    Error: ImagePullBackOff
2m59s       Normal    SuccessfulCreate          replicaset/hello-node-7567d9fdc9   Created pod: hello-node-7567d9fdc9-z879j
2m59s       Normal    ScalingReplicaSet         deployment/hello-node              Scaled up replica set hello-node-7567d9fdc9 to 1
19m         Normal    NodeHasSufficientMemory   node/minikube                      Node minikube status is now: NodeHasSufficientMemory
19m         Normal    NodeHasNoDiskPressure     node/minikube                      Node minikube status is now: NodeHasNoDiskPressure
19m         Normal    NodeHasSufficientPID      node/minikube                      Node minikube status is now: NodeHasSufficientPID
19m         Normal    Starting                  node/minikube                      Starting kubelet.19m         Normal    NodeHasSufficientMemory   node/minikube                      Node minikube status is now: NodeHasSufficientMemory
19m         Normal    NodeHasNoDiskPressure     node/minikube                      Node minikube status is now: NodeHasNoDiskPressure
19m         Normal    NodeHasSufficientPID      node/minikube                      Node minikube status is now: NodeHasSufficientPID
19m         Normal    NodeAllocatableEnforced   node/minikube                      Updated Node Allocatable limit across pods
18m         Normal    RegisteredNode            node/minikube                      Node minikube event: Registered Node minikube in Controller
17m         Normal    Starting                  node/minikube                      Starting kube-proxy.
PS D:\xxxx\Learning> kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority: C:\Users\SnowPhoenix\.minikube\ca.crt
    extensions:
    - extension:
        last-update: Wed, 07 Jul 2021 16:17:25 CST
        provider: minikube.sigs.k8s.io
        version: v1.21.0
      name: cluster_info
    server: https://127.0.0.1:57180
  name: minikube
contexts:
- context:
    cluster: minikube
    extensions:
    - extension:
        last-update: Wed, 07 Jul 2021 16:17:25 CST
        provider: minikube.sigs.k8s.io
        version: v1.21.0
      name: context_info
    namespace: default
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: C:\Users\SnowPhoenix\.minikube\profiles\minikube\client.crt
    client-key: C:\Users\SnowPhoenix\.minikube\profiles\minikube\client.key

可以看到,虽然deployment.apps/hello-node成功创建了,但是却处于不可用状态,有一个ImagePullBackOff报错,从kubectl get events中的信息来看,应该是image pull失败了。

简单查询了一下,原来是因为国内拉不到k8s.gcr.io的镜像。可以通过docker.io的镜像来曲线救国。

先通过镜像拉取镜像:

docker pull mirrorgooglecontainers/echoserver:1.4

然后通过docker tag来“改名”:

docker tag docker.io/mirrorgooglecontainers/echoserver:1.4 k8s.gcr.io/echoserver:1.4

此时通过docker images可以看到k8s.gcr.io/echoserver:1.4镜像已经存存在本地仓库中了:

PS D:\xxxx\Learning> docker images
REPOSITORY                          TAG         IMAGE ID       CREATED        SIZE
mirrorgooglecontainers/echoserver   1.4         a90209bb39e3   5 years ago    140MB
k8s.gcr.io/echoserver               1.4         a90209bb39e3   5 years ago    140MB

然后再删除原先的deployment:

kubectl delete deployment hello-node

然后再重新执行之前的步骤,发现还是不行。重启之后还是不行,就算docker仓库中已经有这个镜像了,启动pods的时候还是会尝试pull。所以只好干脆创建pods的时候就使用镜像:

kubectl create deployment hello-node --image=mirrorgooglecontainers/echoserver:1.4

创建Service

默认情况下,pod只能通过集群中的内部IP地址访问。 要使得hello-node容器可以从k8s虚拟网络的外部访问,我们需要将pod暴露为service。

kubectl expose deployment hello-node --type=LoadBalancer --port=8080

通过以下命令可以查看service的添加情况:

kubectl get services

其中services可以简写为svc

PS D:\xxx\Learning> kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-node   LoadBalancer   10.109.78.212   <pending>     8080:32610/TCP   11s
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          3h32m

可以看到我们添加了名为hello-node、类型为LoadBalancer(负载均衡器)的服务,并且映射到了宿主机端口8080。但是此时访问localhost:8080并不能访问到,还需要执行命令:

minikube service hello-node

我们可以看到命令行输出如下信息:

|-----------|------------|-------------|---------------------------|
| NAMESPACE |    NAME    | TARGET PORT |            URL            |
|-----------|------------|-------------|---------------------------|
| default   | hello-node |        8080 | http://192.168.49.2:32610 |
|-----------|------------|-------------|---------------------------|
🏃  Starting tunnel for service hello-node.
|-----------|------------|-------------|------------------------|
| NAMESPACE |    NAME    | TARGET PORT |          URL           |
|-----------|------------|-------------|------------------------|
| default   | hello-node |             | http://127.0.0.1:63313 |
|-----------|------------|-------------|------------------------|
🎉  正通过默认浏览器打开服务 default/hello-node...
❗  Because you are using a Docker driver on windows, the terminal needs to be open to run it.

访问http://127.0.0.1:63313可以看到,返回了我们所发送的请求的信息:

通过PostMan,我们可以发送其它的信息,也都从响应体中拿到了echo的结果:

启动插件

列出当前支持的插件:

minikube addons list

可以发现有些插件已经启动了:

|-----------------------------|----------|--------------|
|         ADDON NAME          | PROFILE  |    STATUS    |
|-----------------------------|----------|--------------|
| ambassador                  | minikube | disabled     |
| auto-pause                  | minikube | disabled     |
| csi-hostpath-driver         | minikube | disabled     |
| dashboard                   | minikube | enabled ✅   | 
| default-storageclass        | minikube | enabled ✅   | 
| efk                         | minikube | disabled     |
| freshpod                    | minikube | disabled     |
| gcp-auth                    | minikube | disabled     |
| gvisor                      | minikube | disabled     |
| helm-tiller                 | minikube | disabled     |
| ingress                     | minikube | disabled     |
| ingress-dns                 | minikube | disabled     |
| istio                       | minikube | disabled     |
| istio-provisioner           | minikube | disabled     |
| kubevirt                    | minikube | disabled     |
| logviewer                   | minikube | disabled     |
| metallb                     | minikube | disabled     |
| metrics-server              | minikube | disabled     |
| nvidia-driver-installer     | minikube | disabled     |
| nvidia-gpu-device-plugin    | minikube | disabled     |
| olm                         | minikube | disabled     |
| pod-security-policy         | minikube | disabled     |
| registry                    | minikube | disabled     |
| registry-aliases            | minikube | disabled     |
| registry-creds              | minikube | disabled     |
| storage-provisioner         | minikube | enabled ✅   | 
| storage-provisioner-gluster | minikube | disabled     |
| volumesnapshots             | minikube | disabled     |
|-----------------------------|----------|--------------|

启动插件metrics-server

minikube addons enable metrics-server

清理资源

关闭插件metrics-server

minikube addons disable metrics-server

删除服务

kubectl delete service hello-node

删除deployment

kubectl delete deployment hello-node

停止minikube虚拟机

minikube stop

删除minikube虚拟机

minikube delete

小结

今天,我们了解了一些k8s的基本概念,并且尝试进行了一次部署,并成功进行了访问。

下一篇 2021/7/11 Kubernetes学习笔记(二)https://www.cnblogs.com/SnowPhoenix/p/15000280.html

posted @ 2021-07-07 21:22  SnowPhoenix  阅读(514)  评论(0编辑  收藏  举报