写点什么

k8s 中几个基本概念的理解

作者:Java-fenn
  • 2022 年 9 月 12 日
    湖南
  • 本文字数:5547 字

    阅读完需:约 18 分钟

k8s 总体概览

前言

学习 k8s 之前首先对 k8s 中具体的组件做个简单的了解。

Pod

Pod 是 k8s 中集群部署应用和服务的最小单元,一个 pod 中可以部署多个容器。

Pod 的设计理念是支持多个容器在一个 Pod 中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod 对多容器的支持是 K8 最基础的设计理念。

副本控制器(Replication Controller,RC)

RC 是 k8s 集群中最早的保证 Pod 高可用的 API 对象。它的作用就是保证集群中有指定数目的 pod 运行。

当前运行的 pod 数目少于指定的数目,RC 就会启动新的 pod 副本,保证运行 pod 数量等于指定数目。

当前运行的 pod 数目大于指定的数目,RC 就会杀死多余的 pod 副本。

副本集(Replica Set,RS)

RS 是新一代 RC,提供同样的高可用能力,区别主要在于 RS 后来居上,能支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为 Deployment 的理想状态参数使用。

部署(Deployment)

Deployment 提供了一种对 Pod 和 ReplicaSet 的管理方式,每一个 Deployment 都对应集群中的一次部署,是非常常见的 Kubernetes 对象。

Deployment 是一个比 RS 应用模式更广的 API 对象,可以用来创建一个新的服务,更新一个新的服务,也可以用来滚动升级一个服务。

滚动升级一个服务,滚动升级一个服务,实际是创建一个新的 RS,然后逐渐将新 RS 中副本数增加到理想状态,将旧 RS 中的副本数减小到 0 的复合操作;这样一个复合操作用一个 RS 是不太好描述的,所以用一个更通用的 Deployment 来描述。

服务(Service)

RC、RS 和 Deployment 只是保证了支撑服务的微服务 Pod 的数量。但是没有解决如何访问这些服务的问题。

一个 Pod 只是一个运行服务的实例,随时可能在节点上停止,然后再新的节点上用一个新的 IP 启动一个新的 Pod,因此不能使用确定的 IP 和端口号提供服务。这对于业务来说,就不能根据 Pod 的 IP 作为业务调度。kubernetes 就引入了 Service 的概 念,它为 Pod 提供一个入口,主要通过 Labels 标签来选择后端 Pod,这时候不论后端 Pod 的 IP 地址如何变更,只要 Pod 的 Labels 标签没变,那么 业务通过 service 调度就不会存在问题。

同时 service 对绑定的 Pod 提供了负载均衡的功能,我们业务直接使用 service 即可。

当声明 Service 的时候,会自动生成一个 cluster IP,这个 IP 是虚拟 IP。我们就可以通过这个 IP 来访问后端的 Pod,当然,如果集群配置了 DNS 服务,比如现在 的 CoreDNS,那么也可以通过 Service 的名字来访问,它会通过 DNS 自动解析 Service 的 IP 地址。

Service 对外暴露服务的方式

1、ClusterIP (默认) :在集群的内部 IP 上公开 Service 。这种类型使得 Service 只能从集群内访问,一般这种类型的 Service 上层会挂一个 Ingress,通过 Ingress 暴露服务;

2、NodePort:在每个选定 Node 的相同端口上公开 Service,使用 <NodeIP>:<NodePort> 即可从集群外部访问 Service;

3、LoadBalancer:使用云厂商的 K8S 集群,即可使用这种方式的暴露 Service,自建的服务一般不支持。使用 LoadBalancer ,会生成一个 IP 地址,通过这个即可访问 Service, 通知这个 IP 也是高可用的;

4、ExternalName: 通过返回带有该名称的 CNAME 记录,使用任意名称(由 spec 中的 externalName 指定)公开 Service。不使用代理。这种类型需要 kube-dns 的 v1.7 或更高版本。

什么是 CNAME:这种记录允许您将多个名字映射到同一台计算机。

例如:当您拥有多个域名需要指向同一服务器 IP,此时您就可以将一个域名做 A 记录指向服务器 IP,然后将其他的域名做别名(即 CNAME)到 A 记录的域名上;那么当您的服务器 IP 地址变更时,您就可以不必对一个一个域名做更改指向了,只需要更改 A 记录的那个域名到服务器新 IP 上,其他做别名(即 CNAME)的那些域名的指向将自动更改到新的 IP 地址上(以上操作均需要在 DNS 处执行)。

ingress

Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上。

Ingress Controller 就是一个反向代理程序,它负责解析 Ingress 的反向代理规则,如果 Ingress 有增删改的变动,所有的 Ingress Controller 都会及时更新自己相应的转发规则,当 Ingress Controller 收到请求后就会根据这些规则将请求转发到对应的 Service。

Kubernetes 并没有自带 Ingress Controller ,它只是一种标准,具体实现有多种,需要自己单独安装,常用的是 Nginx Ingress Controller 和 Traefik Ingress Controller 。

一个集群中可以有多个 Ingress Controller , 在 Ingress 中可以指定使用哪一个 Ingress Controller 。



Ingress Controller 是部署在集群中的,怎么让 Ingress Controller 本身能够被外面访问到呢?

  • 1、Ingress Controller 用 Deployment 方式部署,给它添加一个 Service,类型为 LoadBalancer,这样会自动生成一个 IP 地址,通过这个 IP 就能访问到了,并且一般这个 IP 是高可用的(前提是集群支持 LoadBalancer,通常云服务提供商才支持,自建集群一般没有);

  • 2、使用 hostPort;

1、 Ingress Controller 用 DaemonSet 方式部署,使用集群内部的某个或某些节点作为边缘节点,给 node 添加 label 来标识,使用 nodeSelector 绑定到边缘节点,保证每个边缘节点启动一个 Ingress Controller 实例,用 hostPort 直接在这些边缘节点宿主机暴露端口,然后我们可以访问边缘节点中 Ingress Controller 暴露的端口,这样外部就可以访问到 Ingress Controller 了;

2、使用非亲缘性策略,使需要部署 Ingress Controller 的节点,每个节点都有一个 Ingress Controller 部署,然后用 hostPort 直接在这些边缘节点宿主机暴露端口,我们就能通过这些节点的 IP 和 hostPort 来访问 Ingress Controller 了。

不过使用 hostPort 这种方式,我们还需要再上面部署一层负载均衡。

什么是 hostPort

这是一种直接定义 Pod 网络的方式。

hostPort 是直接将容器的端口与所调度的节点上的端口路由,这样用户就可以通过宿主机的 IP 加上来访问 Pod 了,比如:

apiVersion: v1kind: Podmetadata:  name: influxdbspec:  containers:    - name: influxdb      image: influxdb      ports:        - containerPort: 8086          hostPort: 8086
复制代码

节点(Node)

k8s 中通过将容器放入到节点 Node 上运行的 Pod 中来执行工作负载。 k8s 中的计算能力就是由 node 提供。

节点可以是物理机也可以是虚拟机,取决于集群的配置,通常 k8s 集群中,有越多的 node 节点,意味着有更强的计算能力。

命名空间(Namespace)

命名空间为 Kubernetes 集群提供虚拟的隔离作用,Kubernetes 集群初始有两个命名空间,分别是默认命名空间 default 和系统命名空间 kube-system,除此以外,管理员可以可以创建新的命名空间满足需要。

名字空间适用于存在很多跨多个团队或项目的用户的场景。对于只有几到几十个用户的集群,根本不需要创建或考虑名字空间。

k8s 中的部署过程

这里用一个简单的栗子来看下,看下 k8s 中应用的部署过程。

1、创建命名空间

$ kubectl create namespace study-k8s
复制代码

2、使用 deployment 部署 pod

$ cat go-web.yaml apiVersion: apps/v1kind: Deploymentmetadata:  creationTimestamp: null  labels:    app: go-web  name: go-web  namespace: study-k8sspec:  replicas: 5  selector:    matchLabels:      app: go-web  strategy: {}  template:    metadata:      creationTimestamp: null      labels:        app: go-web    spec:      containers:      - image: liz2019/test-docker-go-hub        name: go-app-container        resources: {}status: {}
复制代码

运行

$ kubectl apply -f go-web.yaml  -n study-k8s
$ kubectl get pods -n study-k8sNAME READY STATUS RESTARTS AGEgo-web-59f7dc559c-g2hjg 1/1 Running 0 5h21mgo-web-59f7dc559c-g6p8k 1/1 Running 0 5h21mgo-web-59f7dc559c-l4fgm 1/1 Running 0 5h21mgo-web-59f7dc559c-lqvpj 1/1 Running 0 5h21mgo-web-59f7dc559c-rrdjp 1/1 Running 0 5h21m
$ kubectl describe deployment nginx-deploy -n study-k8sName: go-webNamespace: study-k8sCreationTimestamp: Wed, 07 Sep 2022 15:33:58 +0800Labels: app=go-webAnnotations: deployment.kubernetes.io/revision: 1Selector: app=go-webReplicas: 5 desired | 5 updated | 5 total | 5 available | 0 unavailableStrategyType: RollingUpdateMinReadySeconds: 0RollingUpdateStrategy: 25% max unavailable, 25% max surgePod Template: Labels: app=go-web Containers: go-app-container: Image: liz2019/test-docker-go-hub Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none>Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailableOldReplicaSets: <none>NewReplicaSet: go-web-59f7dc559c (5/5 replicas created)Events: <none>
复制代码

Deployment 为 Pod 和 Replica Set 提供声明式更新。所以可以看到创建的 Deployment 里面就同时也创建好了 Replica Set 。

3、为服务创建 service

上面我们创建了一组 Pod ,接下来,我们借助于 service 来实现对这些 Pod 的访问。

$ cat go-web-svc.yaml apiVersion: v1kind: Servicemetadata:  name: go-web-svc  labels:    run: go-web-svcspec:  selector:    app: go-web  ports:    - protocol: TCP      port: 8000      targetPort: 8000      name: go-web-http
复制代码

运行

$ kubectl apply -f go-web-svc.yaml -n study-k8s
$ kubectl get svc -n study-k8sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEgo-web-svc ClusterIP 10.233.9.188 <none> 8000/TCP 37s
$ kubectl describe svc go-web-svc -n study-k8sName: go-web-svcNamespace: study-k8sLabels: run=go-web-svcAnnotations: <none>Selector: app=go-webType: ClusterIPIP: 10.233.9.188Port: go-web-http 8000/TCPTargetPort: 8000/TCPEndpoints: 10.233.111.104:8000,10.233.111.105:8000,10.233.111.106:8000 + 2 more...Session Affinity: NoneEvents: <none>
复制代码

可以看到 service 已经创建完成。

4、配置 ingress 的转发策略

service 已经创建成功了,接下来我们使用 ingress

$ cat go-web-ingress.yaml    apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: go-web-ingress  annotations:    kubernetes.io/ingress.class: nginxspec:  rules:  - host: www.go-web.com    http:      paths:      - path: /index        pathType: Prefix        backend:          service:            name: go-web-svc            port:              number: 8000
复制代码

部署 ingress

$ kubectl apply -f go-web-ingress.yaml -n study-k8s
$ kubectl get ingress -n study-k8sNAME CLASS HOSTS ADDRESS PORTS AGEgo-web-ingress <none> www.go-web.com 11.11.111.113 80 107s
复制代码

通过 ingress 访问

$ curl '11.11.111.113:80/index' \--header 'Host: www.go-web.com'
<h1>hello world</h1><div>你好</div>%
复制代码

也可以在本地添加 host,通过域名访问

$ sudo vi /etc/hosts
// 根据ingress部署的iP11.11.111.113 www.liz-test.com
复制代码



总结

1、Pod 是 k8s 中集群部署应用和服务的最小单元;

2、RC 是 k8s 集群中最早的保证 Pod 高可用的 API 对象。它的作用就是保证集群中有指定数目的 pod 运行;

3、RS 是新一代 RC,提供同样的高可用能力,是目前主要使用的对象;

4、Deployment 提供了一种对 Pod 和 ReplicaSet 的管理方式,RS 的使用都是结合 Deployment 来完成的。

5、一般使用 Deployment 来滚动升级一个服务,滚动升级一个服务,实际是创建一个新的 RS,然后逐渐将新 RS 中副本数增加到理想状态,将旧 RS 中的副本数减小到 0 的复合操作;这样一个复合操作用一个 RS 是不太好描述的,所以用一个更通用的 Deployment 来描述。

6、RC、RS 和 Deployment 只是保证了支撑服务的微服务 Pod 的数量。但是没有解决如何访问这些服务的问题。一个 Pod 只是一个运行服务的实例,随时可能在节点上停止,然后再新的节点上用一个新的 IP 启动一个新的 Pod,因此不能使用确定的 IP 和端口号提供服务。这对于业务来说,就不能根据 Pod 的 IP 作为业务调度。kubernetes 就引入了 Service 的概 念,它为 Pod 提供一个入口,主要通过 Labels 标签来选择后端 Pod,这时候不论后端 Pod 的 IP 地址如何变更,只要 Pod 的 Labels 标签没变,那么 业务通过 service 调度就不会存在问题。

7、Service 是后端真实服务的抽象,一个 Service 可以代表多个相同的后端服务;

8、Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上;

用户头像

Java-fenn

关注

需要Java资料或者咨询可加我v : Jimbye 2022.08.16 加入

还未添加个人简介

评论

发布
暂无评论
k8s中几个基本概念的理解_Java_Java-fenn_InfoQ写作社区