1、创建 Pod
node1,2都下载nginx
[root@k8smaster node]# mkdir service
[root@k8smaster node]# cd service/
[root@k8smaster service]# kubectl delete deploy myapp-v1
deployment.apps "myapp-v1" deleted
[root@k8smaster service]# vim pod_test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80 #pod 中的容器需要暴露的端口
#更新资源清单文件
[root@k8smaster service]# kubectl apply -f pod_test.yaml
deployment.apps/my-nginx created
#查看刚才创建的 Pod ip 地址
[root@k8smaster service]# kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
my-nginx-5898cf8d98-kgwbg 1/1 Running 0 58s 10.244.1.35 k8snode2 <none>
my-nginx-5898cf8d98-tgpst 1/1 Running 0 8s 10.244.1.36 k8snode2 <none>
#请求 pod ip 地址,查看结果
[root@k8smaster service]# curl 10.244.1.35
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[root@k8smaster service]# curl 10.244.1.36
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-kgwbg -- /bin/bash
root@my-nginx-5898cf8d98-kgwbg:/# curl 10.244.1.36
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
root@my-nginx-5898cf8d98-kgwbg:/# exit
exit
需要注意的是,pod 虽然定义了容器端口,但是不会使用调度到该节点上的 80 端口,也不会使用任何特定的 NAT 规则去路由流量到 Pod 上。 这意味着可以在同一个节点上运行多个 Pod,使用相同的容器端口,并且可以从集群中任何其他的 Pod 或节点上使用 IP 的方式访问到它们。
误删除其中一个 Pod:
[root@k8smaster service]# kubectl delete pods my-nginx-5898cf8d98-kgwbg
pod "my-nginx-5898cf8d98-kgwbg" deleted
[root@k8smaster service]# kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
my-nginx-5898cf8d98-cjzs4 1/1 Running 0 6s 10.244.2.36 k8snode <none>
my-nginx-5898cf8d98-tgpst 1/1 Running 0 2m50s 10.244.1.36 k8snode2 <none>
通过上面可以看到重新生成了一个 pod my-nginx-5898cf8d98-cjzs4,ip 是 10.244.2.36,在 k8s 中创建 pod,如果 pod 被删除了,重新生成的 pod ip 地址会发生变化,所以需要在 pod 前端加一个固定接入层。接下来创建 service.
查看 pod 标签:
[root@k8smaster service]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
my-nginx-5898cf8d98-cjzs4 1/1 Running 0 5m29s pod-template-hash=5898cf8d98,run=my-nginx
my-nginx-5898cf8d98-tgpst 1/1 Running 0 8m13s pod-template-hash=5898cf8d98,run=my-nginx
2、创建 Service
[root@xianchaomaster1 service]# vim service_test.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
type: ClusterIP
ports:
- port: 80 #service 的端口,暴露给 k8s 集群内部服务访问
protocol: TCP
targetPort: 80 #pod 容器中定义的端口
selector:
run: my-nginx #选择拥有 run=my-nginx 标签的 pod
上述 yaml 文件将创建一个 Service,具有标签 run=my-nginx 的 Pod,目标 TCP 端口 80,并且在一个抽象的 Service 端口(targetPort:容器接收流量的端口;port:抽象的 Service 端口,可以使任何其它 Pod 访问该 Service 的端口)上暴露。
[root@k8smaster service]# kubectl apply -f service_test.yaml
service/my-nginx created
[root@k8smaster service]# kubectl get svc -l run=my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.110.254.82 <none> 80/TCP 61s
[root@k8smaster service]# kubectl get endpoints
NAME ENDPOINTS AGE
my-nginx 10.244.1.36:80,10.244.2.36:80 2m4s
#可以看到关联了两个pod的ip和端口
#在 k8s 控制节点访问 service 的 ip:端口就可以把请求代理到后端 pod
[root@k8smaster service]# curl 10.110.254.82:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
#通过上面可以看到请求 service IP:port 跟直接访问 pod ip:port 看到的结果一样,这就说明 service 可以把请求代理到它所关联的后端 pod
注意:上面的 10.99.198.177:80 地址只能是在 k8s 集群内部可以访问,在外部无法访问,比方说我们想要通过浏览器访问,那么是访问不通的,如果想要在 k8s 集群之外访问,是需要把 service type 类型改成 nodePort 的
#查看 service 详细信息
[root@k8smaster service]# kubectl describe svc my-nginx
Name: my-nginx
Namespace: default
Labels: run=my-nginx
Annotations: Selector: run=my-nginx
Type: ClusterIP
IP: 10.110.254.82
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.36:80,10.244.2.36:80
Session Affinity: None
Events: <none>
[root@k8smaster service]# kubectl get ep my-nginx
NAME ENDPOINTS AGE
my-nginx 10.244.1.36:80,10.244.2.36:80 11m
service 可以对外提供统一固定的 ip 地址,并将请求重定向至集群中的 pod。其中“将请求重定向至集群中的 pod”就是通过 endpoint 与 selector 协同工作实现。selector 是用于选择 pod,由selector 选择出来的 pod 的 ip 地址和端口号,将会被记录在 endpoint 中。endpoint 便记录了所有 pod的 ip 地址和端口号。当一个请求访问到 service 的 ip 地址时,就会从 endpoint 中选择出一个 ip 地址和端口号,然后将请求重定向至 pod 中。具体把请求代理到哪个 pod,需要的就是 kube-proxy 的轮询实现的。service 不会直接到 pod,service 是直接到 endpoint 资源,就是地址加端口,再由 endpoint 再关联到 pod。
service 只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群 dns 中动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是:
SVC_NAME.NS_NAME.DOMAIN.LTD. 服务名.命名空间.域名后缀 集群默认的域名后缀是 svc.cluster.local
就像我们上面创建的 my-nginx 这个服务,它的完整名称解析就是 my-nginx.default.svc.cluster.local
[root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-tgpst -- /bin/bash
root@my-nginx-5898cf8d98-tgpst:/# curl my-nginx.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
#想让主机访问域名要配置hosts和resolv
[root@k8smaster service]# vim /etc/hosts
加一行10.110.254.82 my-nginx.default.svc.cluster.local
[root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-tgpst -- /bin/bash
root@my-nginx-5898cf8d98-tgpst:/# cat /etc/host
cat: /etc/host: No such file or directory
root@my-nginx-5898cf8d98-tgpst:/# cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.244.1.36 my-nginx-5898cf8d98-tgpst
root@my-nginx-5898cf8d98-tgpst:/# cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
#然后要修改resolv,搜索的时候会在这个文件搜索。
[root@k8smaster service]# vim /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain #搜索的域名
[root@k8smaster service]# curl my-nginx.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
#nameserver要把之前的注释掉,只写coredns的,然后可以在物理机访问,但是如果这么写,物理机一些dns访问会有问题,所以还是要把这个恢复原样.