Kubernetes是集群,所需的一切都包含在该集群中。在其中,您会发现两种类型的节点:控制平面[url=https://kubernetes.io/docs/concepts/architecture/nodes/]节点[/url] 和工作节点节点。
- 控制平面是管理群集资源,负载均衡,健康,多工序的集中设置。Kubernetes集群通常具有多个控制器节点,以实现可用性和负载平衡。作为开发人员,您很可能会通过API网关进行交互。
- 工作节点是运行Kubernetes本地代理Kubelet的任何主机,包括通信 Kube-Proxy.。前者处理控制平面在本地容器运行时(例如docker)上命令的操作,而后者将连接重定向到正确的Pod。
命名空间
运行一段时间后,Kubernetes集群可能会变得庞大且被大量使用。为了使事情井井有条,Kubernetes创建了Namespace命名空间的概念。
命名空间基本上是实际集群内部的虚拟集群。
大多数资源将包含在一个名称空间中,因此不会意识到其他名称空间的资源。只有少数几种资源完全不知道名称空间,它们定义了计算能力或存储源(即节点和PersistentVolumes)。但是,可以通过Quotas的名称空间对这些文件实现限制访问。
当Kubernetes创建并使用名为default的名称空间(如果未指定任何内容)时,可识别名称空间的资源将始终包含在名称空间中。
命名空间不是万灵药,因为它很大程度上取决于您的组织和需求。但是,我们可以注意到一些常用的名称空间用法:
- 按团队或项目划分集群,以避免命名冲突并帮助资源重新分配。
- 除以环境集群(即dev,staging,prod),保持一致的架构。
- 以更细粒度的方式进行部署(例如, 蓝色/绿色部署),以在出现问题时快速退回到未受干扰的工作环境。
配置文件
Kubernetes中的资源是以声明性方式创建的,虽然可以通过命令行配置应用程序部署,但是一种好的做法是在版本化环境中跟踪资源定义。这种做法有时称为GitOps,不仅适用于Kubernetes,而且广泛适用于由DevOps运动支持的交付系统。
为此,Kubernetes提出了资源声明的YAML表示形式,其结构可以总结如下:
apiVersion 全部文件 解析文件时使用的版本。 kind 全部文件 文件描述的资源类型。 metadata 全部文件 资源标识和标签。 data 以数据为中心的文件(机密,ConfigMap) 数据映射的内容入口点。 spec 大多数文件(Pod,Deployment,Ingress等) 资源配置的内容入口点。
|
元数据和标签
元数据条目在创建任何资源时至关重要,因为它使Kubernetes和您自己可以轻松地识别和选择资源。
在此条目中,您需要定义一个name和一个namespace(默认为default),通过它,控制平面将能够自动判断该文件是集群的新添加内容还是先前加载的文件的修订版。
在这些元素之上,您可以定义一个labels部分。它由一组键值对组成,以缩小资源的上下文和内容。
之后,可以通过Selectors在几乎所有CLI命令中使用这些标签。由于这些条目未在Kubernetes的核心行为中使用,因此即使Kubernetes定义了一些最佳做法建议,您也可以使用所需的任何名称。
最后,您还可以创建一个annotations部分,该部分几乎与labelsKubernetes完全相同,但完全没有使用。这些可以在应用程序端用于触发行为,也可以简单地添加数据以简化调试。
# <metadata>缩小选择范围并标识资源 metadata: # <name>条目是必需的,用于标识资源 name: my-resource namespace: my-namespace-or-default # <labels>是可选的,但通常是资源选择所必需的 labels: app: application-name category: back #<annotations>是可选的,不是Kubernetes必需配置 annotations: version: 4.2
|
以数据为中心的配置文件
这些文件定义了键-值映射,以后可以在其他资源中使用。通常,这些资源(即Secrets和ConfigMap)首先加载,因为您的基础结构文件很可能依赖于它们。
apiVersion: v1 # #<kind>定义此文件中描述的资源 kind: ConfigMap metadata: name: my-config data: #<data>配置要加载的数据 configuration_key: "configuration_value" properties_entry: | # 接受任何多行内容 multiline_config=true
|
以基础架构为中心的配置文件
这些文件定义了可能在数据文件中使用的内容,从而在群集上部署了基础结构。
apiVersion: v1 # <kind> 定义此文件中描述的资源 kind: Pod metadata: name: my-web-server spec: # <<spec>是特定于域的资源描述。 # 不同种类的规范条目将非常不同
|
资源定义
在本节中,我们将仔细研究Kubernetes应用程序上最常用的资源的配置。这也是展示资源之间相互作用的机会。
在本节的最后,我们将有一个正在运行的Nginx服务器,并将能够从集群外部与该服务器联系。下图总结了预期的状态:
ConfigMap用于保存可稍后在您的资源中使用的属性。
apiVersion: v1 kind: ConfigMap metadata: name: simple-web-config namespace: default data: configuration_key: "Configuration value"
|
然后,可以使用以下代码段从另一个资源定义中选择上面定义的配置:
valueFrom: configMapKeyRef: name: simple-web-config key: configuration_key
|
注意:ConfigMap仅在定义它们的名称空间中可用。
所有敏感数据都应放在Secret文件中(例如API密钥,密码短语等)。默认情况下,数据仅作为base64编码的值保存,而无需加密。但是,Kubernetes提出了通过集成基于角色的访问控制 或加密机密来减轻泄漏风险的方法 。
Secret文件在其根目录type定义了一个密钥,可用于在data条目中声明的密钥上添加验证。默认情况下,将类型设置为Opaque完全不验证条目的类型。
apiVersion: v1 kind: Secret metadata: name: simple-web-secrets # Opaque<type>可以保存一般机密,因此不会进行验证。 type: Opaque data: # Secrets 应该用base64编码 secret_configuration_key: "c2VjcmV0IHZhbHVl"
|
然后,可以使用以下代码段从另一个资源定义中选择上面定义的Secret:
valueFrom: secretKeyRef: name: simple-web-secrets key: secret_configuration_key
|
Pod定义文件非常简单,但由于可用的配置数量很大,因此可能会变得很大。name和image字段是唯一的强制性的,但你可以经常使用:
- ports 定义要在容器和Pod上打开的端口。
- env 定义要加载到容器上的环境变量。
- args和entrypoint自定义容器启动顺序。
Pod通常不会在Kubernetes上作为独立资源创建,因为最佳实践表明将Pod用作更高级别定义的一部分 (例如,部署)。在这种情况下,Pod文件的内容将简单地嵌入到其他资源的文件中。 1apiVersion: v1 2kind: Pod 3metadata: 4 name: my-web-server 5spec: 6 #<containers>是要嵌入到pod中的容器定义的列表 7 containers: 8 - name: web 9 image: nginx 10 ports: 11 - name: web 12 containerPort: 80 13 protocol: TCP 14 env: 15 - name: SOME_CONFIG 16 # 从ConfigMap数据创建一行“value:<config\u entry>” 17 valueFrom: 18 configMapKeyRef: 19 name: simple-web-config 20 key: configuration_key 21 - name: SOME_SECRET 22 # 从secret数据创建一行“value:<config\u entry>” 23 valueFrom: 24 secretKeyRef: 25 name: simple-web-secrets 26 key: secret_configuration_key
|
注意:Pod仅在定义它们的名称空间中可用。
部署方式
部署Deploy通常用作原子工作单元,因为它将自动执行以下操作:
- 根据template条目创建一个容器定义。
- 在selector条目选择的Pod上创建一个ReplicaSet ,其值为replicas作为应运行的Pod的计数。
以下文件请求始终运行的3个Nginx服务器实例。该文件可能看起来有点沉重,但其中大多数是从上方复制的Pod定义。
1apiVersion: apps/v1 2kind: Deployment 3metadata: 4 name: my-web-server-deployment 5 namespace: default 6 labels: 7 app: webserver 8spec: 9 # #<selector>应该检索下面定义的Pod,可能还有更多 10 selector: 11 matchLabels: 12 app: webserver 13 instance: nginx-ws-deployment 14 # <replicas>定义3个pod始终并行运行 15 replicas: 3 16 #<template>的内容是一个Pod定义文件,没有<apiVersion>或<kind> 17 template: 18 metadata: 19 name: my-web-server 20 namespace: default 21 labels: 22 app: webserver 23 instance: nginx-ws-deployment 24 spec: 25 containers: 26 - name: web 27 image: nginx 28 ports: 29 - name: web 30 containerPort: 80 31 protocol: TCP 32 env: 33 - name: SOME_CONFIG 34 # 从ConfigMap数据创建一行“value:<config\u entry>” 35 valueFrom: 36 configMapKeyRef: 37 name: simple-web-config 38 key: configuration_key 39 - name: SOME_SECRET 40 # 从Secret数据创建一行“value:<config\u entry>” 41 valueFrom: 42 secretKeyRef: 43 name: simple-web-secrets 44 key: secret_configuration_key
|
注意:部署Deploy仅在定义它们的名称空间中可用。
服务Service
pod可以随时删除并重新创建。发生这种情况时,pod的IP地址将更改,如果您直接与其联系,则可能导致连接中断。为了解决此问题,服务可为一组Pod提供稳定的联系点,同时不知道其状态和配置。
通常,通过selector条目将Pod选为服务的一部分,因此基于Pod labels。当且仅当选择器selector 中的所有labels 都被Pod用尽时,才会选择一个Pod。
有行为截然不同三种服务,您可以使用类型条目进行选择:
- ClusterIP服务绑定到从集群的内部IP,因此仅在内部到达。这是默认创建的服务类型,适合于绑定同一集群内的不同应用程序。
- NodePort服务将(在范围30000默认到32767)托管所选Pod节点上绑定的端口。这使您可以直接通过节点IP与服务联系。这也意味着您的服务将像托管这些容器的虚拟机或物理机一样具有可访问性。注意:使用NodePort可能会带来安全风险,因为它可以从群集外部进行直接连接。
- 一个负载平衡器服务会自动创建一个负载均衡器 自该集群正在运行云服务提供商的实例。该负载均衡器是在集群外部创建的,但将自动绑定到托管所选Pod的节点。
下面是一种公开服务的简便方法,但是由于每个服务将由单个负载平衡器管理,因此最终可能会导致成本高昂。
如果您要像我们在此处那样设置自己的Ingress,则可能要使用一种ClusterIp服务,因为针对特定用例提供了其他服务。
1apiVersion: v1 2kind: Service 3metadata: 4 name: simple-web-service-clusterip 5spec: 6 # ClusterIP是<type>默认服务 7 type: ClusterIP 8 # 选择声明<label>条目“app:webserver”的所有pod 9 selector: 10 app: webserver 11 ports: 12 - name: http 13 protocol: TCP 14 # <port>是服务端要绑定的端口 15 port: 80 16 # <targetPort>是Pod侧要绑定的端口 17 targetPort: 80
|
注意:服务在名称空间中定义,但可以从其他名称空间联系。
Ingressr入口
Ingress使您可以发布内部服务,而不必使用云服务提供商的负载平衡器。您通常需要每个命名空间只有一个入口,在那里你可以绑定尽可能多的路由rules和backends你想要的。后端通常是内部路由ClusterIP服务。
请注意,Kubernetes不会自行处理入口资源,而是依赖于第三方实现。因此, 在使用任何入口资源之前,您将必须选择并安装入口控制器。另一方面,它可以根据群集的需求自定义入口资源。
1apiVersion: networking.k8s.io/v1 2kind: Ingress 3metadata: 4 name: simple-web-ingress 5 annotations: 6 nginx.ingress.kubernetes.io/rewrite-target: / 7spec: 8 rules: 9 使用<host>将与给定DNS名称匹配的所有请求重定向到此规则 10 - host: "*.minikube.internal" 11 http: 12 paths: 13 - path: /welcome 14 pathType: Prefix 15 backend: 16 service: 17 name: simple-web-service-clusterip 18 port: 19 number: 80 20 # All other requests will be redirected through this rule 21 - http: 22 paths: 23 - path: / 24 pathType: Prefix 25 backend: 26 service: 27 name: simple-web-service-clusterip 28 port: 29 number: 80
|
注意:入口是在名称空间中定义的,但是可以与其他名称空间的服务联系,并且可以在群集外部公开访问。
更多:
在Minikube上启用入口
Nginx入口注释
创建和管理资源
本节展示了用于操纵资源的基本CLI命令。如前所述,虽然可以手动管理资源,但是更好的做法是使用文件。
1# <kind>是要创建的资源类型(例如部署、secret、命名空间、配额等) 2$ kubectl create <kind> <name> 3$ kubectl edit <kind> <name> 4$ kubectl delete <kind> <name> 5 6所有这些命令都可以通过描述文件使用。 7$ kubectl create -f <resource>.yaml 8$ kubectl edit -f <resource>.yaml 9$ kubectl delete -f <resource>.yaml
|
为了简化通过文件的资源操作,可以将与CLI的交互减少为以下两个命令:
1#创建和更新任何资源 2$ kubectl apply -f <resource>.yaml 3删除任何资源 4$ kubectl delete -f <resource>.yaml
|
监控和调试
您可以使用查看通过CLI运行的所有资源kubectl get <kind>。此命令功能非常强大,可让您筛选要显示或选择要查看的资源的种类。
注意:如果未指定,Kubernetes将在default名称空间上工作。您可以指定-n <namespace>使用特定的名称空间,也-A可以显示每个名称空间。
1# Fetch everything 2$ kubectl get all 3NAME READY STATUS RESTARTS AGE 4pod/my-web-server-deployment-58c4fd887f-5vm2b 1/1 Running 0 128m 5pod/my-web-server-deployment-58c4fd887f-gq6lr 1/1 Running 0 128m 6pod/my-web-server-deployment-58c4fd887f-gs6qb 1/1 Running 0 128m 7 8NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 9service/simple-web-service-clusterip ClusterIP 10.96.96.241 <none> 80/TCP,443/TCP 60m 10service/simple-web-service-lb LoadBalancer 10.108.182.232 <pending> 80:31095/TCP,443:31940/TCP 60m 11service/simple-web-service-np NodePort 10.101.77.203 <none> 80:31899/TCP,443:31522/TCP 60m 12 13NAME READY UP-TO-DATE AVAILABLE AGE 14deployment.apps/my-web-server-deployment 3/3 3 3 136m 15 16NAME DESIRED CURRENT READY AGE 17replicaset.apps/my-web-server-deployment-58c4fd887f 3 3 3 128m 18 19# We can ask for more details 20$ kubectl get deployment -o wide 21NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR 22my-web-server-deployment 3/3 3 3 121m web nginx app=webserver 23 24# Some resources are not visible using "all" but available 25$ kubectl get configmap 26NAME DATA AGE 27kube-root-ca.crt 1 38d 28simple-web-config 3 3h17m
|
挖掘特定资源:
大多数必需的日常操作都可以通过以下三个命令来完成。
- 第一个命令将使用为您提供资源的完整配置kubectl describe <kind>/<name>。
- 另一个重要的命令是kubectl logs <kind>/<name>,您可能期望它会向您显示资源的日志(如果适用)。由于日志是由Pod生成的,因此在Pod上方的资源上运行这样的命令将挖掘Kubernetes,以在其下方显示随机选择的Pod的日志。
- 最后,有时在Pod上连接非常有用,您可以使用命令kubectl进行连接exec -it <pod_name> -- /bin/bash。这将在窗格上打开一个交互式外壳,使您可以与其内容进行交互。
结论
在本文中,我们了解了使用Kubernetes部署和发布无状态服务的基本原理。但是使用Kubernetes可以做很多更复杂的事情。如果您想了解更多信息,我建议您看一下以下资源: