k8s:service资源详解

k8s:service资源详解

Service的作用

  • 解决Pod IP变化问题
  • 解决Pod IP集群外不可访问问题
  • 作为一组同类Pod的对外访问接口
  • 实现服务发现和负载均衡

Service类型

  • ClusterIP:集群内部访问

  • NodePort:集群外部访问

service操作示例

创建集群内部访问的service
复制代码
[root@master ~]# vim deploy-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: xy
spec:
  replicas: 3
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
 #通过service管理需要标签labels相同
[root@master ~]# kubectl apply -f deploy-nginx.yaml
[root@master ~]# kubectl get pods -n xy
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6c45cbd8c5-dg47s   1/1     Running   0          60s
nginx-6c45cbd8c5-h4mrw   1/1     Running   0          60s
nginx-6c45cbd8c5-pqpnl   1/1     Running   0          60s
#暴露service
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx --type=ClusterIP --port=80 --target-port=80 -n xy
service/svc-nginx exposed
#查看service
[root@master ~]# kubectl get svc svc-nginx -n xy -o wide
NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE   SELECTOR
svc-nginx   ClusterIP   10.103.221.167   <none>        80/TCP    54s   run=nginx
#这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的 可以通过这个IP访问当前service对应的POD
[root@master ~]# curl 10.103.221.167:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
创建集群外可访问的service
复制代码
#上面创建的service的type类型为ClusterIP,只有集群内部可访问,将type类型修改为NodePort可以让外部访问
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx1 --type=NodePort --port=80 --target-port=80 -n xy
service/svc-nginx1 exposed
[root@master ~]# kubectl get svc svc-nginx1 -n xy -o wide
NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE   SELECTOR
svc-nginx1   NodePort   10.106.202.74   <none>        80:31766/TCP   59s   run=nginx
#外部访问ip:端口号,集群内的ip都可以访问
删除service
复制代码
[root@master ~]# kubectl delete svc svc-nginx -n xy
service "svc-nginx" deleted
[root@master ~]# kubectl get svc -n xy
NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
svc-nginx1   NodePort   10.106.202.74   <none>        80:31766/TCP   3m49s
创建svc-nginx.yaml
复制代码
#如果不会创建也可以去看官方文档
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx3
  namespace: xy
spec:
  clusterIP: 10.96.0.11
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx
  type: ClusterIP
#这里的clusterIP必须跟下面clusterIP的网段相同
[root@master ~]# kubectl get svc -n kube-system 
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   3d
pod详解
复制代码
#pod资源清单

apiVersion: v1           # 必选,版本号
kind: Pod               # 必选,资源类型
metadata:               # 必选,元数据
  name: string          # 必选,Pod名称
  namespace: string     # Pod所属的命名空间,默认为"default"
  labels:               # 自定义标签列表
    - name: string          
spec:                   # 必选,Pod中容器的详细定义
  containers:           # 必选,Pod中容器列表
  - name: string        # 必选,容器名称
    image: string       # 必选,容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent]  # 获取镜像的策略 
    command: [string]   # 容器的启动命令列表
    args: [string]      # 容器的启动命令参数列表
    workingDir: string  # 容器的工作目录
    
    # 挂载到容器内部的存储卷配置
    volumeMounts:       
    - name: string      # 引用pod定义的共享存储卷名称
      mountPath: string # 存储卷在容器内mount的绝对路径
      readOnly: boolean # 是否为只读模式
    
    # 需要暴露的端口号列表
    ports:             
    - name: string        # 端口名称
      containerPort: int  # 容器需要监听的端口号
      hostPort: int       # 容器所在主机需要监听的端口号
      protocol: string    # 端口协议,支持TCP和UDP,默认TCP
    
    # 容器运行前需设置的环境变量列表
    env:               
    - name: string   # 环境变量名称
      value: string  # 环境变量的值
    
    # 资源限制和请求的设置
    resources:        
      limits:         # 资源限制的设置
        cpu: string    # CPU限制,单位为core数
        memory: string # 内存限制,单位可以为MiB/GiB
      requests:       # 资源请求的设置
        cpu: string    # CPU请求,容器启动的初始可用数量
        memory: string # 内存请求,容器启动的初始可用数量
    
    # 生命周期钩子
    lifecycle:        
      postStart:      # 容器启动后立即执行此钩子
      preStop:        # 容器终止前执行此钩子
    
    # 容器健康检查设置
    livenessProbe:    
      exec:           # exec检查方式
        command: [string]  # exec方式需要执行的命令或脚本
      httpGet:        # HttpGet检查方式
        path: string
        port: number
        host: string
        scheme: string
        httpHeaders:
        - name: string
          value: string
      tcpSocket:      # tcpSocket检查方式
        port: number
      initialDelaySeconds: 0  # 容器启动后首次探测时间(秒)
      timeoutSeconds: 0       # 探测等待响应的超时时间(秒)
      periodSeconds: 0        # 定期探测时间间隔(秒)
      successThreshold: 0
      failureThreshold: 0
    
    securityContext:
      privileged: false
  
  # Pod的重启策略
  restartPolicy: [Always | Never | OnFailure]
  
  # 节点调度相关
  nodeName: <string>        # 指定调度到特定节点
  nodeSelector: object      # 根据label选择调度节点
  
  # 镜像拉取秘钥
  imagePullSecrets:         
  - name: string
  
  # 网络配置
  hostNetwork: false        # 是否使用主机网络模式
  
  # 存储卷配置
  volumes:                  # 共享存储卷列表
  - name: string           # 存储卷名称
    emptyDir: {}           # 临时目录,与Pod同生命周期
    hostPath:              # 宿主机目录挂载
      path: string         # 宿主机目录路径
    secret:                # Secret存储卷
      secretName: string  
      items:     
      - key: string
        path: string
    configMap:             # ConfigMap存储卷
      name: string
      items:
      - key: string
        path: string

通过explain查看某种资源可以配置的一级属性

复制代码
[root@master ~]# kubectl explain pod
KIND:       Pod
VERSION:    v1

DESCRIPTION:
    Pod is a collection of containers that can run on a host. This resource is
    created by clients and scheduled onto hosts.
    
FIELDS:
  apiVersion	<string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind	<string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata	<ObjectMeta>
    Standard object's metadata. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

  spec	<PodSpec>
    Specification of the desired behavior of the pod. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

  status	<PodStatus>
    Most recently observed status of the pod. This data may not be up to date.
    Populated by the system. Read-only. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
    
#查看
[root@master ~]# kubectl explain pod.kind
KIND:       Pod
VERSION:    v1

FIELD: kind <string>

DESCRIPTION:
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:
1、apiVersion 版本,由kubernetes内部定义,版本号必须可以用 kubectl api-versions 查询到
2、kind 类型,由kubernetes内部定义,版本号必须可以用 kubectl api-resources 查询到
3、metadata 元数据,主要是资源标识和说明,常用的有name、namespace、labels等
4、spec描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述
5、status状态信息,里面的内容不需要定义,由kubernetes自动生成

containers - 容器列表
类型:<[]Object>(对象数组)

作用:定义Pod中运行的一个或多个容器

2. nodeName - 节点名称
作用:强制将Pod调度到指定名称的Node节点

使用场景:需要精确控制Pod运行位置时

注意:跳过正常的调度器,直接指定节点

3. nodeSelector - 节点选择器
类型:<map[]>(键值对映射)

作用:根据Node的label标签选择调度目标

工作机制:选择包含指定label的Node进行调度

4. hostNetwork - 主机网络模式
类型:布尔值

默认值:false

作用:

false:使用Pod独立网络命名空间

true:直接使用宿主机网络(共享网络栈)

5. volumes - 存储卷
类型:<[]Object>(对象数组)

作用:定义Pod级别的存储卷

用途:容器间共享数据、持久化存储

常见类型:

emptyDir、hostPath

configMap、secret

持久卷(PersistentVolume)

6. restartPolicy - 重启策略
作用:定义Pod在遇到故障时的处理策略

可选值:

Always:总是重启(默认)

OnFailure:失败时重启

Never:从不重启
pod配置
复制代码
[root@master ~]# kubectl explain pod.spec.containers
KIND:       Pod
VERSION:    v1

FIELD: containers <[]Container>

DESCRIPTION:
    List of containers belonging to the pod. Containers cannot currently be
    added or removed. There must be at least one container in a Pod. Cannot be
    updated.
    A single application container that you want to run within a pod.
    
FIELDS:
  args	<[]string>
    Arguments to the entrypoint. The container image's CMD is used if this is
    not provided. Variable references $(VAR_NAME) are expanded using the
    container's environment. If a variable cannot be resolved, the reference in
    the input string will be unchanged. Double $$ are reduced to a single $,
    which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
    produce the string literal "$(VAR_NAME)". Escaped references will never be
    expanded, regardless of whether the variable exists or not. Cannot be
.........

 name  <string>     # 容器名称
   image <string>     # 容器需要的镜像地址
   imagePullPolicy  <string> # 镜像拉取策略 
   command  <[ ]string> # 容器的启动命令列表,如不指定,使用打包时使用的启动命令
   args     <[ ]string> # 容器的启动命令需要的参数列表
   env      <[ ]Object> # 容器环境变量的配置
   ports    <[ ]Object>     # 容器需要暴露的端口号列表
   resources <Object>      # 资源限制和资源请求的设置
创建pod-baseyaml
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-base
  namespace: xy
  labels:
    user: user1
spec:
  containers:
  - name: nginx
    image: nginx:latest
  - name: busybox
    image: busybox:1.30
[root@master ~]# kubectl apply -f pod-base.yaml 
pod/pod-base created
[root@master ~]# kubectl get pod -n xy
NAME                     READY   STATUS     RESTARTS      AGE
nginx-6c45cbd8c5-dg47s   1/1     Running    0             70m
nginx-6c45cbd8c5-h4mrw   1/1     Running    0             70m
nginx-6c45cbd8c5-pqpnl   1/1     Running    0             70m
pod-base                 1/2     NotReady   3 (31s ago)   51s
#这里有一个NotReady,原因是busybox并不是一个程序,而是类似于一个工具类的集合,kubernetes集群启动管理后,它会自动关闭。解决方法就是让其一直在运行,需要用到command配置

apiVersion: v1
kind: Pod
metadata:
  name: pod-base
  namespace: xy
  labels:
    user: user1
spec:
  containers:
  - name: nginx
    image: nginx:latest
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]
 #每隔3秒向文件中写入当前时间,能够让buybox一直运行
   
[root@master ~]# kubectl delete -f pod-base.yaml
pod "pod-base" deleted
[root@master ~]# kubectl apply -f pod-base.yaml 
pod/pod-base created
[root@master ~]# kubectl get pod -n xy
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6c45cbd8c5-dg47s   1/1     Running   0          72m
nginx-6c45cbd8c5-h4mrw   1/1     Running   0          72m
nginx-6c45cbd8c5-pqpnl   1/1     Running   0          72m
pod-base                 2/2     Running   0          15s
#再次查看发现变成了Running
#进入pod中的busybox容器
格式:kubectl exec  pod名称 -n 命名空间 -it -c 容器名称 /bin/sh
[root@master ~]# kubectl exec pod-base -n xy -it -c busybox /bin/sh
[root@master ~]# kubectl exec pod-base -n xy -it -c busybox /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # tail -f /tmp/hello.txt
07:51:34
07:51:37
07:51:40
07:51:43
07:51:46
07:51:49
07:51:52
07:51:55
#Kubernetes 中的 command 和 args 字段用于覆盖 Docker 镜像中的默认启动命令,它们与 Dockerfile 中的 ENTRYPOINT 和 CMD 指令存在对应关系

场景	适用情况	示例
只设置 command	需要完全自定义启动流程	执行特定脚本或命令
只设置 args	保持原有启动程序,仅修改参数	调整服务配置参数
两者都设置	需要自定义解释器和命令	使用 shell 执行复杂命令
具体覆盖规则如下:
如果command和args均没有写:那么使用Docker镜像中的默认配置,即ENTRYPOINT和CMD。

如果只写了command:那么容器启动时执行command中指定的命令,Docker镜像中的ENTRYPOINT和CMD都被忽略。args不会被使用。

如果只写了args:那么Docker镜像中的ENTRYPOINT命令会被执行,并使用args中的参数替换Docker镜像中的CMD。即ENTRYPOINT不变,CMD被替换为args。

如果command和args都写了:那么容器启动时执行command中指定的命令,并使用args中的参数。Docker镜像中的ENTRYPOINT和CMD都被忽略

imagePullPolicy,用于设置镜像拉取策略,kubernetes支持配置三种拉取策略
Always:总是从远程仓库拉取镜像(一直远程下载)
IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地 本地没远程下载)
Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错 (一直使用本地)
如果镜像tag为具体版本号, 默认策略是:IfNotPresent
如果镜像tag为:latest(最终版本) ,默认策略是always
env用于在pod中的容器设置环境变量
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-base
  namespace: xy
  labels:
    user: user1
spec:
  containers:
  - name: nginx
    image: nginx:latest
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]
    env:
    - name: "username"
      value: "admin"
    - name: "password"
      value: "redhat"
 这种方式不推荐,推荐将这些配置单独存储在配置文件中

查看ports支持的子选项
[root@master ~]# kubectl explain pod.spec.containers.ports
KIND:       Pod
VERSION:    v1

FIELD: ports <[]ContainerPort>

DESCRIPTION:
    List of ports to expose from the container. Not specifying a port here DOES
    NOT prevent that port from being exposed. Any port which is listening on the
    default "0.0.0.0" address inside a container will be accessible from the
    network. Modifying this array with strategic merge patch may corrupt the
    data. For more information See
    https://github.com/kubernetes/kubernetes/issues/108255. Cannot be updated.
    ContainerPort represents a network port in a single container.
    
FIELDS:
  containerPort	<integer> -required-
    Number of port to expose on the pod's IP address. This must be a valid port
    number, 0 < x < 65536.

  hostIP	<string>
    What host IP to bind the external port to.

  hostPort	<integer>
    Number of port to expose on the host. If specified, this must be a valid
    port number, 0 < x < 65536. If HostNetwork is specified, this must match
    ContainerPort. Most containers do not need this.

  name	<string>
    If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
    named port in a pod must have a unique name. Name for the port that can be
    referred to by services.

  protocol	<string>
    Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP".
    
    Possible enum values:
     - `"SCTP"` is the SCTP protocol.
     - `"TCP"` is the TCP protocol.
     - `"UDP"` is the UDP protocol
     
#  name         <string>  # 端口名称,如果指定,必须保证name在pod中是唯一的		
   containerPort<integer> # 容器要监听的端口(0<x<65536)
   hostPort     <integer> # 容器要在主机上公开的端口,如果设置,主机上只能运行容器的一个副本(一般省略) 
   hostIP       <string>  # 要将外部端口绑定到的主机IP(一般省略)
   protocol     <string>  # 端口协议。必须是UDP、TCP或SCTP。默认为"TCP"
创建pod-ports.yaml
复制代码
[root@master ~]# vim pod-ports.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-ports
  namespace: xy
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - name: nginx-port
      containerPort: 80
      protocol: TCP

[root@master ~]# kubectl apply -f pod-ports.yaml 
pod/pod-ports created
[root@master ~]# kubectl get pods -n xy
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6c45cbd8c5-dg47s   1/1     Running   0          88m
nginx-6c45cbd8c5-h4mrw   1/1     Running   0          88m
nginx-6c45cbd8c5-pqpnl   1/1     Running   0          88m
pod-base                 2/2     Running   0          16m
pod-ports                1/1     Running   0          35s
#访问容器中的程序需要使用的是Podip:containerPort
[root@master ~]# kubectl get pod pod-ports -n xy -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
pod-ports   1/1     Running   0          73s   172.16.166.143   node1   <none>           <none>

[root@master ~]# curl 172.16.166.143
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
需要注意如果一个pod里面的两个容器都监听一个80端口,那么有一个容器不会运行,如果运行的是nginx,那么即使在yaml文件里修改端口不相同,也会有一个不运行,因为nginx的配置文件里面默认监控80端口,需要修改nginx的配置文件中的监听端口来解决
复制代码
预先规划:在设计多容器 Pod 时,确保各容器使用不同的监听端口

配置检查:确认容器内应用程序的实际监听端口与 YAML 配置一致

测试验证:部署前通过 kubectl logs 和 kubectl describe 检查容器状态

资源配额

复制代码
资源管理的必要性
容器在运行过程中需要消耗 CPU、内存等系统资源。如果不对容器资源使用进行限制,可能出现以下问题:

资源抢占:单个容器过度占用资源,导致其他容器无法正常运行

系统不稳定:资源耗尽可能引起节点故障或系统崩溃

性能不可预测:缺乏资源保障导致应用性能波动

资源配额机制
Kubernetes 通过 resources 选项提供精细化的资源管理能力,包含两个关键子选项:

1. requests - 资源请求
作用:定义容器需要的最小资源保障

调度依据:Kubernetes 根据此值选择有足够资源的节点

启动条件:如果集群无法满足资源请求,容器将无法启动

2. limits - 资源限制
作用:设置容器能够使用的最大资源上限

强制约束:当容器资源使用超过限制时会被强制终止并重启

保护机制:防止单个容器耗尽节点资源
创建pod-resources.yaml
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-resources
  namespace: xy
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    imagePullPolicy: Never
    resources:       
      limits:     
        cpu: "2"     
        memory: "10Gi"   
      requests:     
        cpu: "1"
        memory: "10Mi"
#cpu:core数,可以为整数或小数
memory: 内存大小,可以使用Gi、Mi、G、M等形式
#这里要注意,resources内存的下限值不能超过宿主机的内存

通过 requests 和 limits 的配合使用,Kubernetes 实现了:

资源预留:确保容器获得基本资源保障

资源隔离:防止容器间相互干扰

资源限制:维持集群整体稳定性

合理调度:基于实际需求进行智能调度决策

这种机制既保证了关键应用的资源可用性,又有效防止了资源滥用,是 Kubernetes 集群稳定运行的重要保障
相关推荐
hello_2503 小时前
Shell脚本高效编写技巧
运维·shell
Dovis(誓平步青云)3 小时前
《静态库与动态库:从编译原理到实战调用,一篇文章讲透》
linux·运维·开发语言
不开心就吐槽3 小时前
linux安装kafka
linux·运维·kafka
孙同学要努力3 小时前
《Linux篇》进程等待(wait、waitpid)与进程程序替换(exec等接口)
linux·服务器·网络
柯衍ky3 小时前
Mac通过命令行开启ssh服务
运维·macos·ssh
_w_z_j_4 小时前
Linux----进程控制
linux·运维·服务器
chinesegf10 小时前
Docker篇4-本地项目app.py与docker加载项目镜像的开发顺序
运维·docker·容器
CyreneSimon10 小时前
Docker 拉取配置教程:解决镜像拉取连接超时问题
运维·docker·容器
李子红了时11 小时前
【墨铺网教程】一台电脑加入多个局域网,让电脑做上传下载主力又当存储盘
运维·服务器·电脑