这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。
Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
#创建
[root@master ~]# kubectl create ns yhm
namespace/yhm created
[root@master ~]# kubectl create deploy nginx --image=nginx:latest --port=80 --replicas=3 -n yhm
deployment.apps/nginx created#暴露Service
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n yhm
service/svc-nginx1 exposed# 查看service
[root@master ~]# kubectl get svc svc-nginx1 -n yhm -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-nginx1 ClusterIP 10.109.147.6 80/TCP 26s app=nginx# 这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的
# 可以通过这个IP访问当前service对应的POD[root@master ~]# kubectl get svc svc-nginx1 -n yhm -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-nginx1 ClusterIP 10.109.147.6 80/TCP 89s app=nginx
[root@master ~]# curl 10.109.147.6
Welcome to nginx!
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.
For online documentation and support please refer to
nginx.org.
Commercial support is available at
nginx.com.
Thank you for using nginx.
# 上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问# 如果需要创建外部也可以访问的Service,需要修改type为NodePort
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n yhm
service/svc-nginx2 exposed# 此时查看,会发现出现了NodePort类型的Service,而且有一对Port(80:32349/TCP )
[root@master ~]# kubectl get svc svc-nginx2 -n yhm -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-nginx2 NodePort 10.109.247.254 80:31403/TCP 38s app=nginx# 接下来就可以通过集群外的主机访问 节点IP:31403访问服务了# 例如在的电脑主机上通过浏览器访问下面的地址http://192.168.223.176:31403/

删除Service
[root@master ~]# kubectl delete svc svc-nginx2 -n yhm
service "svc-nginx2" deleted
配置方式
创建一个svc-nginx.yaml,内容如下:
[root@master ~]# vim svc-nginx.yaml
[root@master ~]# cat svc-nginx.yaml
apiVersion: v1
kind: Service
metadata:name: svc-nginxnamespace: yhm
spec:clusterIP: 10.109.247.254ports:- port: 80protocol: TCPtargetPort: 80selector:run: nginxtype: ClusterIP
[root@master ~]# kubectl create -f svc-nginx.yaml
service/svc-nginx created
[root@master ~]# kubectl delete -f svc-nginx.yaml
service "svc-nginx" deleted
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,资源类型,例如 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定义的共享存储卷的名称,需用volumes[]部分定义的的卷名mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符readOnly: boolean #是否为只读模式ports: #需要暴露的端口库号列表- name: string #端口的名称containerPort: int #容器需要监听的端口号hostPort: int #容器所在主机需要监听的端口号,默认与Container相同protocol: string #端口协议,支持TCP和UDP,默认TCPenv: #容器运行前需设置的环境变量列表- name: string #环境变量名称value: string #环境变量的值resources: #资源限制和请求的设置limits: #资源限制的设置cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数requests: #资源请求的设置cpu: string #Cpu请求,容器启动的初始可用数量memory: string #内存请求,容器启动的初始可用数量lifecycle: #生命周期钩子postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器exec: #对Pod容器内检查方式设置为exec方式command: [string] #exec方式需要制定的命令或脚本httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、portpath: stringport: numberhost: stringscheme: stringHttpHeaders:- name: stringvalue: stringtcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式port: numberinitialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次successThreshold: 0failureThreshold: 0securityContext:privileged: falserestartPolicy: [Always | Never | OnFailure] #Pod的重启策略nodeName: #设置NodeName表示将该Pod调度到指定到名称的node节点上nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定- name: stringhostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络volumes: #在该pod上定义共享存储卷列表- name: string #共享存储卷名称 (volumes类型有很多种)emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录path: string #Pod所在宿主机的目录,将被用于同期中mount的目录secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部scretname: string items: - key: stringpath: stringconfigMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部name: stringitems:- key: stringpath: string
小提示:
# 在这里,可通过一个命令来查看每种资源的可配置项# kubectl explain 资源类型 查看某种资源可以配置的一级属性# kubectl explain 资源类型.属性 查看属性的子属性
[root@k8s-master01 ~]# kubectl explain pod
KIND: Pod
VERSION: v1
FIELDS:apiVersion kind metadata
在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:
在上面的属性中,spec是接下来研究的重点,继续看下它的常见子属性:
pod.spec.containers属性
[root@master01 ~]# kubectl explain pod.spec.containers
KIND: Pod
VERSION: v1
RESOURCE: containers <[ ]Object> # 数组,代表可以有多个容器
FIELDS:name # 容器名称image # 容器需要的镜像地址imagePullPolicy # 镜像拉取策略 command <[ ]string> # 容器的启动命令列表,如不指定,使用打包时使用的启动命令args <[ ]string> # 容器的启动命令需要的参数列表env <[ ]Object> # 容器环境变量的配置ports <[ ]Object> # 容器需要暴露的端口号列表resources # 资源限制和资源请求的设置
创建pod-base.yaml文件,内容如下
[root@master ~]# vim pod-base.yaml
[root@master ~]# cat pod-base.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-basenamespace: yhmlabels:user: user1
spec:containers:- name: nginximage: nginx:1.17.1- name: busyboximage: busybox:1.30//上面定义了一个比较简单Pod的配置,里面有两个容器:
nginx:用1.17.1版本的nginx镜像创建,(nginx是一个轻量级web容器)
busybox:用1.30版本的busybox镜像创建,(busybox是一个小巧的linux命令集合)[root@master ~]# kubectl create -f pod-base.yaml
pod/pod-base created
[root@master ~]# kubectl get pod -n yhm
NAME READY STATUS RESTARTS AGE
nginx-cd55c47f5-cd28w 1/1 Running 0 55m
nginx-cd55c47f5-pqbb8 1/1 Running 0 55m
nginx-cd55c47f5-qjc7p 1/1 Running 0 55m
pod-base 0/2 ContainerCreating 0 19s
创建pod-imagepullpolicy.yaml文件:
[root@master ~]# vim pod-imagepullpolicy.yaml
[root@master ~]# cat pod-imagepullpolicy.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-imagepullpolicynamespace: yhm
spec:containers:- name: nginximage: nginx:1.17.1imagePullPolicy: Never- name: busyboximage: busybox:1.30imagePullPolicy,用于设置镜像拉取策略,kubernetes支持配置三种拉取策略:Always:总是从远程仓库拉取镜像(一直远程下载)
IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地 本地没远程下载)
Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错 (一直使用本地)默认值说明:
如果镜像tag为具体版本号, 默认策略是:IfNotPresent
如果镜像tag为:latest(最终版本) ,默认策略是always
[root@master ~]# kubectl create -f pod-imagepullpolicy.yaml
pod/pod-imagepullpolicy created
在前面的案例中,一直有一个问题没有解决,就是的busybox容器一直没有成功运行,那么到底是什么原因导致这个容器的故障呢?
原来busybox并不是一个程序,而是类似于一个工具类的集合,kubernetes集群启动管理后,它会自动关闭。解决方法就是让其一直在运行,这就用到了command配置。
[root@master ~]# vim pod-command.yaml
[root@master ~]# cat pod-command.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-command1namespace: yhm
spec:containers:- name: nginximage: nginx:1.17.1imagePullPolicy: Never- name: busyboximage: busybox:1.30imagePullPolicy: Nevercommand: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]command,用于在pod中的容器初始化完毕之后运行一个命令。稍微解释下上面命令的意思:“/bin/sh”,“-c”, 使用sh执行命令touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中写入当前时间[root@master ~]# kubectl create -f pod-command.yam
pod/pod-command1 created
[root@master ~]# kubectl get pods -n yhm
NAME READY STATUS RESTARTS AGE
nginx-cd55c47f5-cd28w 1/1 Running 0 62m
nginx-cd55c47f5-pqbb8 1/1 Running 0 62m
nginx-cd55c47f5-qjc7p 1/1 Running 0 62m
pod-base 1/2 CrashLoopBackOff 6 (73s ago) 7m34s
pod-command1 0/2 ErrImageNeverPull 0 15s
pod-imagepullpolicy 1/2 CrashLoopBackOff 5 (15s ago) 3m20s# 进入pod中的busybox容器,查看文件内容
# 补充一个命令: kubectl exec pod名称 -n 命名空间 -it -c 容器名称 /bin/sh 在容器内部执行命令
# 使用这个命令就可以进入某个容器的内部,然后进行相关操作了
# 比如,可以查看txt文件的内容特别说明:通过上面发现command已经可以完成启动命令和传递参数的功能,为什么这里还要提供一个args选项,用于传递参数呢?这其实跟docker有点关系,kubernetes中的command、args两项其实是实现覆盖Dockerfile中ENTRYPOINT的功能。1 如果command和args均没有写,那么用Dockerfile的配置。2 如果command写了,但args没有写,那么Dockerfile默认的配置会被忽略,执行输入的command3 如果command没写,但args写了,那么Dockerfile中配置的ENTRYPOINT的命令会被执行,使用当前args的参数4 如果command和args都写了,那么Dockerfile的配置被忽略,执行command并追加上args参数
[root@master ~]# vim pod-env.yaml
[root@master ~]# cat pod-env.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-envnamespace: yhm
spec:containers:- name: busyboximage: busybox:1.30imagePullPolicy: Nevercommand: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60; done;"]env:- name: "username"value: "admin"- name: "password"value: "redhat"env,环境变量,用于在pod中的容器设置环境变量。
[root@master ~]# kubectl create -f pod-env.yaml
pod/pod-env created
[root@master ~]# kubectl exec pod-env -n yhm -c busybox -it /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo $username
admin
/ # echo $password
redhat
/ # exit
本小节来介绍容器的端口设置,也就是containers的ports选项。
首先看下ports支持的子选项:
[root@k8s-master01 ~]# kubectl explain pod.spec.containers.ports
KIND: Pod
VERSION: v1
RESOURCE: ports <[ ]Object>
FIELDS:name # 端口名称,如果指定,必须保证name在pod中是唯一的 containerPort # 容器要监听的端口(0 # 容器要在主机上公开的端口,如果设置,主机上只能运行容器的一个副本(一般省略) hostIP # 要将外部端口绑定到的主机IP(一般省略)protocol # 端口协议。必须是UDP、TCP或SCTP。默认为“TCP”。
接下来,编写一个测试案例,创建pod-ports.yaml
[root@master ~]# vim pod-ports.yaml
[root@master ~]# cat pod-ports.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-portsnamespace: yhm
spec:containers:- name: nginximage: nginx:1.17.1imagePullPolicy: Neverports:- name: nginx-portcontainerPort: 80protocol: TCP
[root@master ~]# kubectl create -f pod-ports.yaml
pod/pod-ports created
[root@master ~]# kubectl get pod -n yhm
NAME READY STATUS RESTARTS AGE
nginx-cd55c47f5-cd28w 1/1 Running 0 84m
nginx-cd55c47f5-pqbb8 1/1 Running 0 84m
nginx-cd55c47f5-qjc7p 1/1 Running 0 84m
pod-base 1/2 CrashLoopBackOff 10 (2m38s ago) 29m
pod-command1 0/2 ErrImageNeverPull 0 22m
pod-env 0/1 ErrImageNeverPull 0 15m
pod-imagepullpolicy 1/2 CrashLoopBackOff 9 (3m59s ago) 25m
pod-ports 1/1 Running 0 14s
[root@master ~]# kubectl get pod pod-ports -n yhm -o yaml
apiVersion: v1
kind: Pod
metadata:creationTimestamp: "2022-11-29T16:02:22Z"name: pod-portsnamespace: yhmresourceVersion: "11199"uid: 3b6345d5-ee3e-4764-a6e2-6d56242c8e90
spec:containers:- image: nginx:1.17.1imagePullPolicy: Nevername: nginxports:- containerPort: 80name: nginx-portprotocol: TCPresources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /var/run/secrets/kubernetes.io/serviceaccountname: kube-api-access-q9shbreadOnly: truednsPolicy: ClusterFirstenableServiceLinks: truenodeName: node1preemptionPolicy: PreemptLowerPrioritypriority: 0restartPolicy: AlwaysschedulerName: default-schedulersecurityContext: {}serviceAccount: defaultserviceAccountName: defaultterminationGracePeriodSeconds: 30tolerations:- effect: NoExecutekey: node.kubernetes.io/not-readyoperator: ExiststolerationSeconds: 300- effect: NoExecutekey: node.kubernetes.io/unreachableoperator: ExiststolerationSeconds: 300volumes:- name: kube-api-access-q9shbprojected:defaultMode: 420sources:- serviceAccountToken:expirationSeconds: 3607path: token- configMap:items:- key: ca.crtpath: ca.crtname: kube-root-ca.crt- downwardAPI:items:- fieldRef:apiVersion: v1fieldPath: metadata.namespacepath: namespace
status:conditions:- lastProbeTime: nulllastTransitionTime: "2022-11-29T16:02:22Z"status: "True"type: Initialized- lastProbeTime: nulllastTransitionTime: "2022-11-29T16:02:24Z"status: "True"type: Ready- lastProbeTime: nulllastTransitionTime: "2022-11-29T16:02:24Z"status: "True"type: ContainersReady- lastProbeTime: nulllastTransitionTime: "2022-11-29T16:02:22Z"status: "True"type: PodScheduledcontainerStatuses:- containerID: containerd://79e58eb15f8bbbd5ffb5fb55da09f61860ff6a548a213c1c5152ebf59c524c3dimage: docker.io/library/nginx:1.17.1imageID: docker.io/library/nginx@sha256:b4b9b3eee194703fc2fa8afa5b7510c77ae70cfba567af1376a573a967c03dbblastState: {}name: nginxready: truerestartCount: 0started: truestate:running:startedAt: "2022-11-29T16:02:23Z"hostIP: 192.168.223.177phase: RunningpodIP: 10.244.1.7podIPs:- ip: 10.244.1.7qosClass: BestEffortstartTime: "2022-11-29T16:02:22Z"访问容器中的程序需要使用的是Podip:containerPort
[root@master ~]# kubectl get pod pod-ports -n yhm -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-ports 1/1 Running 0 4m7s 10.244.1.7 node1
[root@master ~]# curl http://10.244.1.7
Welcome to nginx!